Repository navigation
Harden backup and restore: recursive discovery, content fidelity, safe targets (card 71) - #21
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c6caeab2f1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| process.exit(1); | ||
| } | ||
|
|
||
| const config = loadConfig(process.env); |
There was a problem hiding this comment.
Avoid requiring application secrets for full backups
On a backup or recovery host configured only with Firestore credentials, this new loadConfig() call aborts because config.ts requires both MCP_ADMIN_TOKEN and GEMINI_API_KEY. Neither secret is used by the full-backup operation, and the previous command worked without them. The same dependency was added to full restore, unnecessarily blocking recovery when application secrets are unavailable. Read and validate the embedding settings independently of the application's authentication and Gemini configuration.
Useful? React with 👍 / 👎.
| const expectedFileName = ndjsonFileName(entry.path); | ||
| if (entry.ndjson !== expectedFileName) { | ||
| problems.push( | ||
| `ndjson file name mismatch for ${entry.path}: expected ${expectedFileName}, got ${entry.ndjson}` | ||
| ); |
There was a problem hiding this comment.
Accept original filenames when validating v1 archives
For legacy archives containing collection IDs with spaces, Unicode, or other URI-escaped characters, this comparison rejects valid backups. The previous backup implementation used ${collectionId}.ndjson, whereas ndjsonFileName() now applies encodeURIComponent(). Although readManifest() normalizes v1 entries, it retains their original filenames, so a collection such as release notes always fails validation and cannot be restored. Validate legacy filenames using the v1 naming convention while retaining the encoded convention for v2.
Useful? React with 👍 / 👎.
| if (isDocumentReference(value)) { | ||
| const encoded: EncodedReference = { | ||
| __fs: "reference", | ||
| path: value.path | ||
| }; |
There was a problem hiding this comment.
Preserve database identity in archived document references
If a document contains a reference to another project or named database, recording only value.path loses the referenced database's identity. Restore then resolves every reference through target.referenceFor(p), silently redirecting that external reference into the restore target. Content verification also encodes only the relative path, so it reports success despite the changed reference. Preserve the reference's project/database identity and distinguish external references from references intentionally migrated with the source database.
Useful? React with 👍 / 👎.
Summary
Hardens Firestore backup and restore fidelity, validation, and target protection (card 71 RECOVERY):
GeoPoint,Buffer/Uint8Arraybytes,DocumentReference, and non-finite numbers (NaN,Infinity,-Infinity). Enforces loud failure for unrecognized types and reserved__fsfield keys. IntroducedstableStringifyfor byte-identical recursive serialization regardless of key order.metacortex-firestore-full-backup-v2with per-collection SHA256 checksums, document counts, byte counts, and observed vector dimensions. Manifest is written last, ensuring partial runs never leave invalid manifests. Stale NDJSON files are removed automatically. Full backward compatibility with v1 manifests.validateArchiveruns in dry-run and write mode before any target writes. Validates schema, file existence, SHA256 checksums, JSON syntax, unique IDs, tag decoding, and vector dimensions.my-brain-88870. Restoring to source project requires--target-prefixor explicit confirmation. Default write mode is upsert-only;--pruneand--clear-target-collectionsrequire--confirm-project <target>. Aborts on vector model/dimension mismatches or unknown embedding spaces before any writes.RESTORE INCOMPLETE: ... re-run the same command to finish; upserts are idempotent.validatePortableArchivechecking schema, IDs, content, retrieval text, metadata timestamps, and danglingsuperseded_bylinks before writes. Guarded live collection writes with--replace-liveand--confirm-collection.functions/test/recovery.test.tsusingInMemoryMirrorStore, and real emulator tests infunctions/test/recovery.emulator.test.tsexercising recursive discovery, backup, restore, real Firestore types, content corruption detection, and vector similarity search.docs/FULL_BACKUP.md,docs/MEMORY_ARCHIVE.md, and appended the dated local verification record tometacortexplan.md.🤖 Generated with Claude Code