From 3db77418d740512815f758b7aa9aac0fd4c231fe Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 29 Aug 2026 13:45:49 +0530 Subject: [PATCH 1/2] feat: point migration at phcode.dev now that it serves migrateAssist LEGACY_ORIGIN was staging while the flow was validated end to end. phcode.io now ships migrateAssist.html and the Filer bundle at the paths the migration expects, so the origin actually holding the unmigrated data becomes the source and the comments that described it as staging go with it. The pinned literal in the constants spec is updated alongside. It is not an incidental fixture: LEGACY_ORIGIN is not exported, so that literal is what would catch a staging origin reaching production and quietly pointing the migration at the wrong storage. Note the ordering this implies: web.phcode.dev now frames phcode.dev for the handshake, so until the phcode.io build is deployed there the handshake times out and migration no ops. Boot is unaffected either way. --- .../MigrateAssist/constants.js | 14 +++++++------- test/spec/Extn-MigrateAssist-test.js | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/extensionsIntegrated/MigrateAssist/constants.js b/src/extensionsIntegrated/MigrateAssist/constants.js index 606bbc2329..f8081e8d3c 100644 --- a/src/extensionsIntegrated/MigrateAssist/constants.js +++ b/src/extensionsIntegrated/MigrateAssist/constants.js @@ -22,8 +22,8 @@ * Shared configuration for the one time move off the legacy web origin onto web.phcode.dev. * * Everything that has to change when the rollout moves forward lives here: the two origins and the - * sunset date. `LEGACY_ORIGIN` points at staging while the flow is being validated end to end; - * flipping it to https://phcode.dev is the only edit needed to go live. + * sunset date. `LEGACY_ORIGIN` is live and points at phcode.dev, which serves migrateAssist.html + * and still holds the data of everyone who has not moved across yet. * * @module extensionsIntegrated/MigrateAssist/constants */ @@ -33,11 +33,11 @@ define(function (require, exports, module) { // render identically in every locale, so they stay here instead of going through strings.js. /** - * The origin we are migrating away from. Switch to "https://phcode.dev" once the flow has been - * validated against staging. + * The origin we are migrating away from. It must keep serving migrateAssist.html for as long as + * migration is offered, since that page is what reads the old storage. * @type {string} */ - const LEGACY_ORIGIN = "https://staging.phcode.dev"; + const LEGACY_ORIGIN = "https://phcode.dev"; /** * The origin we are migrating to. @@ -143,8 +143,8 @@ define(function (require, exports, module) { /** * Hostname of the origin being retired, for use inside user facing sentences. Derived from the - * origin rather than written out separately so the two can never disagree, which matters while - * the legacy origin still points at staging. + * origin rather than written out separately so the two can never disagree, which matters because + * the dev override below can repoint the legacy origin. * @return {string} */ function getLegacyDomainName() { diff --git a/test/spec/Extn-MigrateAssist-test.js b/test/spec/Extn-MigrateAssist-test.js index d999926c14..e4e7c68030 100644 --- a/test/spec/Extn-MigrateAssist-test.js +++ b/test/spec/Extn-MigrateAssist-test.js @@ -70,8 +70,9 @@ define(function (require, exports, module) { it("should ignore the dev override inside test windows", function () { // The override exists so the flow can be exercised locally. It must never apply in // a test window, otherwise a stray localStorage value could repoint a real - // migration. - expect(Constants.getLegacyOrigin()).toBe("https://staging.phcode.dev"); + // migration. Pinning the literals also catches a staging origin being shipped to + // production, which would point the migration at the wrong storage. + expect(Constants.getLegacyOrigin()).toBe("https://phcode.dev"); expect(Constants.getNewOrigin()).toBe("https://web.phcode.dev"); }); From f0238b960f3e5291580d31b2f98bfbd4c682531a Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 29 Aug 2026 13:52:51 +0530 Subject: [PATCH 2/2] feat: drop the retirement date from the migration flow The move is happening now rather than on an announced schedule, so the dialog on the outgoing origin no longer counts down to a cutoff. It states that the move is under way and leaves it there, which is also the honest thing to show: naming a date we might not hold to is worse than naming none. That removes SUNSET_DATE along with daysToSunset and isPastSunset, the two countdown strings, and the specs covering them. The guard this takes out of migrator was not cosmetic. It disabled automatic migration once past SUNSET_DATE, which was three days away, so the feature would have switched itself off almost immediately after the move began. What it was really protecting against, probing an origin that is gone on every boot forever, is already covered by MAX_AUTO_ATTEMPTS, and covered better: one attempt and one retry per user, rather than one global date that has to be guessed correctly in advance. MIGRATE_MANUAL_DOWNLOAD_NOTE pointed Safari users at "the date above", which no longer exists, so it now just asks them to download their projects. The sunset-dialog module name and its metric event names are kept as they are. No date is involved in either, and renaming the events would break continuity with what has already been collected. --- .../MigrateAssist/constants.js | 40 +++---------------- .../MigrateAssist/migrator.js | 9 +---- .../MigrateAssist/sunset-dialog.js | 10 ++--- src/nls/root/strings.js | 4 +- test/spec/Extn-MigrateAssist-test.js | 29 -------------- 5 files changed, 11 insertions(+), 81 deletions(-) diff --git a/src/extensionsIntegrated/MigrateAssist/constants.js b/src/extensionsIntegrated/MigrateAssist/constants.js index f8081e8d3c..d4ff92e380 100644 --- a/src/extensionsIntegrated/MigrateAssist/constants.js +++ b/src/extensionsIntegrated/MigrateAssist/constants.js @@ -21,9 +21,12 @@ /** * Shared configuration for the one time move off the legacy web origin onto web.phcode.dev. * - * Everything that has to change when the rollout moves forward lives here: the two origins and the - * sunset date. `LEGACY_ORIGIN` is live and points at phcode.dev, which serves migrateAssist.html - * and still holds the data of everyone who has not moved across yet. + * Everything that has to change when the rollout moves forward lives here, which is the two + * origins. `LEGACY_ORIGIN` is live and points at phcode.dev, which serves migrateAssist.html and + * still holds the data of everyone who has not moved across yet. + * + * There is deliberately no retirement date. The move has no announced cutoff, and the runaway + * probe case the date used to guard is already bounded per user by MAX_AUTO_ATTEMPTS. * * @module extensionsIntegrated/MigrateAssist/constants */ @@ -51,12 +54,6 @@ define(function (require, exports, module) { */ const NEW_DOMAIN_NAME = "web.phcode.dev"; - /** - * The day the legacy origin stops serving. Month is 0 based, so 8 is September. - * @type {number} - */ - const SUNSET_DATE = Date.UTC(2026, 8, 1); - /** * PhStore key recording that the migration already ran. Once set, the automatic path never runs * again and the user has to ask for it from the Help menu. @@ -174,30 +171,7 @@ define(function (require, exports, module) { return !(Phoenix.browser.desktop.isSafari || Phoenix.browser.mobile.isIos); } - /** - * Whole days left before the legacy origin is retired, floored at 0. - * @param {number} [now] current time in ms, for tests - * @return {number} - */ - function daysToSunset(now) { - const millisPerDay = 24 * 60 * 60 * 1000; - const remaining = SUNSET_DATE - (typeof now === "number" ? now : Date.now()); - if (remaining <= 0) { - return 0; - } - return Math.ceil(remaining / millisPerDay); - } - - /** - * @param {number} [now] current time in ms, for tests - * @return {boolean} true once the legacy origin is expected to be gone - */ - function isPastSunset(now) { - return (typeof now === "number" ? now : Date.now()) >= SUNSET_DATE; - } - exports.NEW_DOMAIN_NAME = NEW_DOMAIN_NAME; - exports.SUNSET_DATE = SUNSET_DATE; exports.MIGRATION_DONE_KEY = MIGRATION_DONE_KEY; exports.MIGRATION_ATTEMPTS_KEY = MIGRATION_ATTEMPTS_KEY; exports.MAX_AUTO_ATTEMPTS = MAX_AUTO_ATTEMPTS; @@ -208,6 +182,4 @@ define(function (require, exports, module) { exports.isLegacyOrigin = isLegacyOrigin; exports.isNewOrigin = isNewOrigin; exports.isMigrationSupportedBrowser = isMigrationSupportedBrowser; - exports.daysToSunset = daysToSunset; - exports.isPastSunset = isPastSunset; }); diff --git a/src/extensionsIntegrated/MigrateAssist/migrator.js b/src/extensionsIntegrated/MigrateAssist/migrator.js index 6555386e79..90d3b54dd9 100644 --- a/src/extensionsIntegrated/MigrateAssist/migrator.js +++ b/src/extensionsIntegrated/MigrateAssist/migrator.js @@ -582,19 +582,12 @@ define(function (require, exports, module) { Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "migrateAssist", "skipOutOfAttempts"); return; } - // Once the legacy origin is gone there is nothing to probe, so the feature disables itself - // rather than opening a doomed iframe on every boot forever. - if (Constants.isPastSunset()) { - Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "migrateAssist", "skipPastSunset"); - return; - } Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "migrateAssist", "autoProbe"); run(false); } /** - * Help menu entry point. Ignores the done flag and the sunset date, and always says what - * happened. + * Help menu entry point. Ignores the done flag and always says what happened. */ async function runManually() { Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "migrateAssist", "manualInvoked"); diff --git a/src/extensionsIntegrated/MigrateAssist/sunset-dialog.js b/src/extensionsIntegrated/MigrateAssist/sunset-dialog.js index d599cd61f4..66d96a2f79 100644 --- a/src/extensionsIntegrated/MigrateAssist/sunset-dialog.js +++ b/src/extensionsIntegrated/MigrateAssist/sunset-dialog.js @@ -21,6 +21,9 @@ /** * The "we are moving" dialog, shown on the origin being retired on every boot. * + * It states that the move is happening, with no countdown and no cutoff date: the move is under way + * now, and naming a date we might not hold to would be worse than naming none. + * * Three variants, differing only in the primary button and the closing sentence: * - default, sends the user to the new site where their data migrates automatically; * - Trusted Web Activity, sends the user to the Play Store instead, because the installed app only @@ -56,13 +59,6 @@ define(function (require, exports, module) { paragraphs.push(StringUtils.format(Strings.MIGRATE_MOVING_MESSAGE, Constants.getLegacyDomainName(), Constants.NEW_DOMAIN_NAME)); - if (!Constants.isPastSunset()) { - const days = Constants.daysToSunset(); - paragraphs.push(StringUtils.format( - days === 1 ? Strings.MIGRATE_SUNSET_COUNTDOWN_ONE : Strings.MIGRATE_SUNSET_COUNTDOWN, - days, Constants.getLegacyDomainName())); - } - if (!Constants.isMigrationSupportedBrowser()) { paragraphs.push(Strings.MIGRATE_MANUAL_DOWNLOAD_NOTE); } else { diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 29df45b94f..d3798b1d8d 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -2925,10 +2925,8 @@ define({ // Migration off the legacy web origin onto the new home "MIGRATE_MOVING_TITLE": "{0} is moving", "MIGRATE_MOVING_MESSAGE": "{APP_NAME} on {0} is moving to a new home at {1}. Everything works the same, only the address changes.", - "MIGRATE_SUNSET_COUNTDOWN": "You have {0} days left before {1} stops working.", - "MIGRATE_SUNSET_COUNTDOWN_ONE": "You have {0} day left before {1} stops working.", "MIGRATE_DATA_SAFE_NOTE": "Your projects, settings and extensions will be copied over for you the first time you open {0}. Nothing is deleted from this site.", - "MIGRATE_MANUAL_DOWNLOAD_NOTE": "Automatic transfer is not available in this browser. If you have projects saved here, please download them before the date above so you can open them again on the new site.", + "MIGRATE_MANUAL_DOWNLOAD_NOTE": "Automatic transfer is not available in this browser. If you have projects saved here, please download them so you can open them again on the new site.", "MIGRATE_GO_TO_NEW_SITE": "Take me to the new site", "MIGRATE_STAY_HERE": "Stay here", "MIGRATE_PROGRESS_TITLE": "Bringing your data over", diff --git a/test/spec/Extn-MigrateAssist-test.js b/test/spec/Extn-MigrateAssist-test.js index e4e7c68030..baaff6d2ea 100644 --- a/test/spec/Extn-MigrateAssist-test.js +++ b/test/spec/Extn-MigrateAssist-test.js @@ -34,37 +34,8 @@ define(function (require, exports, module) { describe("unit:MigrateAssist", function () { - const DAY = 24 * 60 * 60 * 1000; - describe("constants", function () { - describe("daysToSunset", function () { - - it("should count whole days remaining", function () { - expect(Constants.daysToSunset(Constants.SUNSET_DATE - (10 * DAY))).toBe(10); - expect(Constants.daysToSunset(Constants.SUNSET_DATE - DAY)).toBe(1); - }); - - it("should round a part day up, so the last day never reads as zero", function () { - expect(Constants.daysToSunset(Constants.SUNSET_DATE - 1)).toBe(1); - expect(Constants.daysToSunset(Constants.SUNSET_DATE - (DAY + 1))).toBe(2); - }); - - it("should floor at zero on and after the sunset date", function () { - expect(Constants.daysToSunset(Constants.SUNSET_DATE)).toBe(0); - expect(Constants.daysToSunset(Constants.SUNSET_DATE + DAY)).toBe(0); - }); - }); - - describe("isPastSunset", function () { - - it("should be false before the date and true on or after it", function () { - expect(Constants.isPastSunset(Constants.SUNSET_DATE - 1)).toBe(false); - expect(Constants.isPastSunset(Constants.SUNSET_DATE)).toBe(true); - expect(Constants.isPastSunset(Constants.SUNSET_DATE + DAY)).toBe(true); - }); - }); - describe("origins", function () { it("should ignore the dev override inside test windows", function () {