From 943daf58d519710d7658697efa12d351c30c7d9f Mon Sep 17 00:00:00 2001 From: Andrew Kostka Date: Wed, 8 Jul 2026 13:29:57 +0000 Subject: [PATCH 1/6] Add initial terms of use policy via migration --- ...249_create_initial_terms_of_use_policy.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php diff --git a/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php b/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php new file mode 100644 index 00000000..09d4b17d --- /dev/null +++ b/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php @@ -0,0 +1,30 @@ + self::POLICY_TYPE, + 'active_from' => self::ACTIVE_FROM, + 'content_vue_file' => 'terms-of-use/version-1.vue', + ]); + } + + /** + * Reverse the migrations. + */ + public function down(): void { + Policy::where([ + 'policy_type' => self::POLICY_TYPE, + 'active_from' => self::ACTIVE_FROM, + ])->delete(); + } +}; From c654da0b927d5e82eaf2659c1ae9933eb6b37a06 Mon Sep 17 00:00:00 2001 From: Andrew Kostka Date: Wed, 8 Jul 2026 13:41:51 +0000 Subject: [PATCH 2/6] Fix linting --- .../2026_07_08_080249_create_initial_terms_of_use_policy.php | 1 + 1 file changed, 1 insertion(+) diff --git a/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php b/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php index 09d4b17d..b8b1ec53 100644 --- a/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php +++ b/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php @@ -5,6 +5,7 @@ return new class() extends Migration { private const POLICY_TYPE = 'terms-of-use'; + private const ACTIVE_FROM = '2022-01-01'; /** From 23e540e12f3f02ae41ea4b7c12a20ba137b4e2c5 Mon Sep 17 00:00:00 2001 From: Andrew Kostka Date: Thu, 9 Jul 2026 07:33:48 +0000 Subject: [PATCH 3/6] Use DB facade instead of models in migration --- ...7_08_080249_create_initial_terms_of_use_policy.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php b/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php index b8b1ec53..77f392a5 100644 --- a/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php +++ b/database/migrations/2026_07_08_080249_create_initial_terms_of_use_policy.php @@ -1,9 +1,11 @@ insert([ 'policy_type' => self::POLICY_TYPE, 'active_from' => self::ACTIVE_FROM, 'content_vue_file' => 'terms-of-use/version-1.vue', + 'created_at' => $now, + 'updated_at' => $now, ]); } @@ -23,7 +28,7 @@ public function up(): void { * Reverse the migrations. */ public function down(): void { - Policy::where([ + DB::table(self::TABLE_NAME)->where([ 'policy_type' => self::POLICY_TYPE, 'active_from' => self::ACTIVE_FROM, ])->delete(); From 9cb545d1bdcbc799368d62cbd6a2270f2c47808e Mon Sep 17 00:00:00 2001 From: Andrew Kostka Date: Tue, 14 Jul 2026 07:39:04 +0000 Subject: [PATCH 4/6] Add migration to backfill terms of use --- ...kfill_policy_acceptance_existing_users.php | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php diff --git a/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php b/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php new file mode 100644 index 00000000..fbe37635 --- /dev/null +++ b/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php @@ -0,0 +1,63 @@ +getPolicyId(); + $timestamp = now(); + + DB::table('users') + ->leftJoin('policy_acceptances', fn ($join) => + $join->on('users.id', '=', 'user_id') + ->where('policy_id', '=', $policyId) + ) + ->whereNull('policy_id') + ->where('users.created_at', '<', self::USER_CREATED_AT_CUTOFF) + ->orderBy('users.id') + ->select('users.id', 'users.created_at') + ->chunkById(100, fn ($users) => + DB::table('policy_acceptances')->insert( + $users->map(fn ($user) => [ + 'user_id' => $user->id, + 'policy_id' => $policyId, + 'accepted_at' => $user->created_at, + 'created_at' => $timestamp, + 'updated_at' => $timestamp, + ])->all() + ), + 'users.id', 'id'); + } + + /** + * Reverse the migrations. + */ + public function down(): void { + DB::table('policy_acceptances') + ->where('policy_id', $this->getPolicyId()) + ->where('accepted_at', '<', self::USER_CREATED_AT_CUTOFF) + ->whereColumn('created_at', '>', 'accepted_at') + ->delete(); + } + + /** + * @return int The policy ID of our existing terms of use. + */ + private function getPolicyId(): int { + return DB::table('policies') + ->where('policy_type', 'terms-of-use') + ->where('active_from', '2022-01-01') + ->soleValue('id'); + } +}; From 272d4ebab9ff8b38103042c9a13cc55d6dbd4219 Mon Sep 17 00:00:00 2001 From: Andrew Kostka Date: Tue, 14 Jul 2026 07:52:35 +0000 Subject: [PATCH 5/6] Fix linting --- ...kfill_policy_acceptance_existing_users.php | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php b/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php index fbe37635..c48bbc27 100644 --- a/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php +++ b/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php @@ -19,25 +19,23 @@ public function up(): void { $timestamp = now(); DB::table('users') - ->leftJoin('policy_acceptances', fn ($join) => - $join->on('users.id', '=', 'user_id') - ->where('policy_id', '=', $policyId) + ->leftJoin('policy_acceptances', fn ($join) => $join->on('users.id', '=', 'user_id') + ->where('policy_id', '=', $policyId) ) ->whereNull('policy_id') ->where('users.created_at', '<', self::USER_CREATED_AT_CUTOFF) ->orderBy('users.id') ->select('users.id', 'users.created_at') - ->chunkById(100, fn ($users) => - DB::table('policy_acceptances')->insert( - $users->map(fn ($user) => [ - 'user_id' => $user->id, - 'policy_id' => $policyId, - 'accepted_at' => $user->created_at, - 'created_at' => $timestamp, - 'updated_at' => $timestamp, - ])->all() - ), - 'users.id', 'id'); + ->chunkById(100, fn ($users) => DB::table('policy_acceptances')->insert( + $users->map(fn ($user) => [ + 'user_id' => $user->id, + 'policy_id' => $policyId, + 'accepted_at' => $user->created_at, + 'created_at' => $timestamp, + 'updated_at' => $timestamp, + ])->all() + ), + 'users.id', 'id'); } /** From a495679bf362b00df7b6bd3b9a314d7f681dcade Mon Sep 17 00:00:00 2001 From: Andrew Kostka Date: Mon, 20 Jul 2026 12:47:58 +0000 Subject: [PATCH 6/6] Remove USER_CREATED_AT_CUTOFF check --- ..._075347_backfill_policy_acceptance_existing_users.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php b/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php index c48bbc27..904a7ba6 100644 --- a/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php +++ b/database/migrations/2026_07_13_075347_backfill_policy_acceptance_existing_users.php @@ -4,13 +4,6 @@ use Illuminate\Support\Facades\DB; return new class() extends Migration { - /** - * Users created before this timestamp are treated as having accepted - * our existing terms of use. Users created afterwards go through our - * new policy flow (T430529) and are excluded from the backfill. - */ - private const USER_CREATED_AT_CUTOFF = '2026-07-13 08:00:00'; - /** * Run the migrations. */ @@ -23,7 +16,6 @@ public function up(): void { ->where('policy_id', '=', $policyId) ) ->whereNull('policy_id') - ->where('users.created_at', '<', self::USER_CREATED_AT_CUTOFF) ->orderBy('users.id') ->select('users.id', 'users.created_at') ->chunkById(100, fn ($users) => DB::table('policy_acceptances')->insert( @@ -44,7 +36,6 @@ public function up(): void { public function down(): void { DB::table('policy_acceptances') ->where('policy_id', $this->getPolicyId()) - ->where('accepted_at', '<', self::USER_CREATED_AT_CUTOFF) ->whereColumn('created_at', '>', 'accepted_at') ->delete(); }