fix(destination): stop propagating source DSN to destination database documents#180
fix(destination): stop propagating source DSN to destination database documents#180
Conversation
… documents Restore an opt-in resolver for `_databases.database` on the Appwrite destination so cross-instance migrations don't write the source's DSN into the destination project's metadata. Without a resolver, the field is left blank and the runtime falls back to the destination project's DSN — correct for legacy single-DSN projects. Why: PR #151 removed the `getDatabaseDSN` callable on the assumption it was unused, and replaced it with `\$resource->getDatabase()` (the source DSN). On Cloud this routed destination reads to the source's host with the destination's project sequence as the namespace, producing `Table 'appwrite._<tenant>__metadata' doesn't exist` for every migrated database. Multi-type setups (documentsdb / vectorsdb) were silently broken the same way. Refs PR #151.
Greptile SummaryThis PR fixes an incident where source-project DSNs were being written into the destination's
Confidence Score: 5/5Safe to merge — the fix is surgical, backward-compatible, and directly addresses the incident root cause. The change touches only the three write/compare sites for No files require special attention. The test file exercises the helper through reflection rather than via createDatabase() (noted in the existing PR thread), but the production code itself is correct and consistent. Important Files Changed
Reviews (4): Last reviewed commit: "fix(destination): use resolveDestination..." | Re-trigger Greptile |
"Cross-instance migrations" was ambiguous: it read like cloud-to-cloud or dedicated-DB migration. The actual scope is narrower — any case where the source project's stored DSN doesn't apply to the destination project (cross-host within the same instance, cross-region, mixed shared-tables migration). Reword the property, constructor, and inline write-site comments to say that explicitly.
There was a problem hiding this comment.
Pull request overview
This PR fixes Appwrite→Appwrite migrations that accidentally wrote the source database DSN into the destination project’s _databases.database metadata, by reintroducing an opt-in destination-DSN resolver and defaulting to writing a blank value so the runtime can fall back to the destination project’s DSN.
Changes:
- Add an optional
getDatabaseDSNresolver toDestinations\Appwriteand use it when writing_databases.database. - Stop writing
$resource->getDatabase()(source DSN) into destination database documents in both create and overwrite paths. - Add a unit regression test covering resolver/no-resolver behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/Migration/Destinations/Appwrite.php |
Introduces an opt-in destination DSN resolver and uses it when persisting _databases.database. |
tests/Migration/Unit/Destinations/AppwriteDestinationDsnTest.php |
Adds regression coverage to ensure the source DSN is never propagated and resolver behavior is honored. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…nature Agent-Logs-Url: https://github.com/utopia-php/migration/sessions/d317b600-9533-45b9-b24b-59eb2df45014 Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
…stead of source DSN Agent-Logs-Url: https://github.com/utopia-php/migration/sessions/f7af1371-ec8c-49fd-bb9e-932ae59e7d6e Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Summary
getDatabaseDSNresolver onDestinations\Appwrite._databases.databaseblank so the runtime falls back to the destination project's DSN. Never write the source's DSN.CreateandOverwritebranches ofcreateDatabase().Why
PR #151 ("Refactor Appwrite migration to remove unused getDatabaseDSN callable …") removed the destination-DSN resolver on the assumption it was unused, and replaced its call site with
$resource->getDatabase()— the source's DSN. Any Appwrite→Appwrite migration where the source and destination projects don't share the same DSN (cross-host within the same cloud instance, cross-region, mixed shared-tables migration) then wrote the source's host string into the destination project's_databasesrows.On Cloud this triggered the comuneo-pre-production incident: destination reads opened a pool to the source host, then derived the namespace from the destination project's sequence (because the source's value isn't in
_APP_DATABASE_SHARED_TABLES), producingfor every database the user touched, and silently aborted the per-table schema creates so destination data was unrecoverable from the request path.
Behavior
_databases.databasewritten as''— runtime falls back to the destination project's DSNThe fallback is never the source DSN, so consumers that don't update get safer behavior than today.
Follow-up
new DestinationAppwrite(…)and bump this dependency. (Done inappwrite-labs/cloud#3979, which also adds a worker-level regression test.)_*_databases.databaserows from earlier migrations. (Done inappwrite-labs/cloud#3977.)Test plan
composer test(Unit)composer lint(Pint)composer check(PHPStan level 3)tests/Migration/Unit/Destinations/AppwriteDestinationDsnTest.php🤖 Generated with Claude Code