From f6c890213bb0e502b02e2de65ef3ffc82f0c02c0 Mon Sep 17 00:00:00 2001 From: alvis Date: Wed, 15 Apr 2026 09:09:08 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20complete=20M0=20=E2=80=94=20legal=20pag?= =?UTF-8?q?es,=20consent,=20tip=5Fviews=20metrics,=20account=20deletion=20?= =?UTF-8?q?UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /legal/terms and /legal/privacy pages (linked from sign-in) - Consent (consentGiven=true) recorded on first Google sign-in - tip_views table: one row per tip served — enables activation + reaction rate queries - tip_views purged on account deletion - Delete account button on /connect (confirm → revoke tokens → purge data → sign out) Co-Authored-By: Claude Sonnet 4.6 --- .../page-2026-04-14T14-06-03-068Z.yml | 2 + .../page-2026-04-14T14-06-13-022Z.png | Bin 0 -> 15588 bytes .../page-2026-04-14T14-06-35-398Z.yml | 119 ++++++++++++++++++ .../page-2026-04-14T14-12-07-158Z.yml | 16 +++ .../page-2026-04-14T14-12-17-872Z.yml | 2 + .../page-2026-04-14T14-14-53-788Z.yml | 16 +++ .../page-2026-04-14T14-26-57-754Z.yml | 119 ++++++++++++++++++ .../page-2026-04-15T07-41-23-867Z.yml | 16 +++ .../page-2026-04-15T08-09-40-643Z.yml | 16 +++ apps/web/src/app/connect/page.tsx | 28 ++++- apps/web/src/app/legal/privacy/page.tsx | 41 ++++++ apps/web/src/app/legal/terms/page.tsx | 39 ++++++ apps/web/src/app/tip/page.tsx | 8 +- apps/web/tsconfig.tsbuildinfo | 2 +- services/api/src/db/schema.ts | 8 ++ services/api/src/routes/auth.ts | 2 +- services/api/src/routes/recommender.ts | 10 +- services/api/src/routes/user.ts | 3 +- 18 files changed, 438 insertions(+), 9 deletions(-) create mode 100644 .playwright-mcp/page-2026-04-14T14-06-03-068Z.yml create mode 100644 .playwright-mcp/page-2026-04-14T14-06-13-022Z.png create mode 100644 .playwright-mcp/page-2026-04-14T14-06-35-398Z.yml create mode 100644 .playwright-mcp/page-2026-04-14T14-12-07-158Z.yml create mode 100644 .playwright-mcp/page-2026-04-14T14-12-17-872Z.yml create mode 100644 .playwright-mcp/page-2026-04-14T14-14-53-788Z.yml create mode 100644 .playwright-mcp/page-2026-04-14T14-26-57-754Z.yml create mode 100644 .playwright-mcp/page-2026-04-15T07-41-23-867Z.yml create mode 100644 .playwright-mcp/page-2026-04-15T08-09-40-643Z.yml create mode 100644 apps/web/src/app/legal/privacy/page.tsx create mode 100644 apps/web/src/app/legal/terms/page.tsx diff --git a/.playwright-mcp/page-2026-04-14T14-06-03-068Z.yml b/.playwright-mcp/page-2026-04-14T14-06-03-068Z.yml new file mode 100644 index 0000000..368a768 --- /dev/null +++ b/.playwright-mcp/page-2026-04-14T14-06-03-068Z.yml @@ -0,0 +1,2 @@ +- main [ref=e2] [cursor=pointer]: + - generic [ref=e3]: ··· \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-14T14-06-13-022Z.png b/.playwright-mcp/page-2026-04-14T14-06-13-022Z.png new file mode 100644 index 0000000000000000000000000000000000000000..c3bddfd834f5c5e36b43ed09ad72aa44ce084520 GIT binary patch literal 15588 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 literal 0 HcmV?d00001 diff --git a/.playwright-mcp/page-2026-04-14T14-06-35-398Z.yml b/.playwright-mcp/page-2026-04-14T14-06-35-398Z.yml new file mode 100644 index 0000000..a20859a --- /dev/null +++ b/.playwright-mcp/page-2026-04-14T14-06-35-398Z.yml @@ -0,0 +1,119 @@ +- generic [ref=e3]: + - generic [ref=e5]: + - generic [ref=e8]: + - img "Google" [ref=e10] + - generic [ref=e11]: Sign in with Google + - generic [ref=e12]: + - generic [ref=e14]: + - heading "Sign in" [level=1] [ref=e15] + - paragraph [ref=e16]: + - text: to continue to + - button "alogins.net" [ref=e17] [cursor=pointer] + - generic [ref=e18]: + - generic [ref=e21]: + - generic [ref=e26]: + - textbox "Email or phone" [active] [ref=e27] + - generic: + - generic: Email or phone + - paragraph [ref=e28]: + - link "Forgot email?" [ref=e29] [cursor=pointer]: + - /url: /signin/v2/usernamerecovery?app_domain=https://o.alogins.net&client_id=225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com&code_challenge=oJlG0iJD7GEnZ_p0tMbi56r9QGirq6lY0KHNKh-A7sI&code_challenge_method=S256&continue=https://accounts.google.com/signin/oauth/legacy/consent?authuser%3Dunknown%26part%3DAJi8hAP_s0wcqLhX3B4DTcLADDDkyjYYD_dTsSJST_xu2o-PkobLfbuk1XhXVndyBN6gkOnR0zh89fZIeMovlOB4w8i9PC5L8hRlhSDi_OSh3ki0cAZ8RRH7CMPl0NmSZbAb7253b7Sq7Uj7dN8TmsRtXQbgjYmbhyQtpViFok9UeZM7XROiV83I_xwzDvOMQD1WQkkCPL_ZjRyGIpPgmLbBXxUWwGnWs7x0CLlb2wOYMM4diy8wjIIVzACtLq0g_hnnf0y_mxrQYevSjMx1y6vLEeMZrKz4zXxSwX11OP6adWx8v9lVviJvM53GJLq4oV46GDTGcxuXLkt9W6FBgRJqMoh1oulT8tHVf1O4VG6FuQkvXnppbkH8b9OMEnqTaVlL1DVwPrvaEytsqZ79DQ74hKi9NiK3RE9wkvTaSElEARWCxILbbRjXR-GKwwybfKjQwGUZ9t2sYcJdZK3ygn8vZIYDrPIKQM8g27tJTfNj5yjjYJZsv-EMRSSvheUtOMdNBzy7fqqBKvxGQEO3iDfgy88NdOrw1AktvipSuf5E5uVlJ5KPLTq5J8TuKHO9TQcmBu9Fn1U1_NwlvMkvWbPJ2zbkshNe2q200XCnKF6Wz1bLG7sukKzEoyJkmc3x7poz1z9JQ4f7%26flowName%3DGeneralOAuthFlow%26as%3DS356240196%253A1776175595013373%26client_id%3D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%23&dsh=S356240196:1776175595013373&flowName=GeneralOAuthLite&o2v=2&opparams=%253F&rart=ANgoxceHU_HzI34dur-e3VKjuSW_62nNyS0F-NAT8vowVRgzLCH8LgeU-dR_jmgEfEI3TjNPYuzeB6EBCMum_GguMnKcbkqUwFjfpff8YscBkT3joDYra5Q&redirect_uri=https://o.alogins.net/api/auth/callback&response_type=code&scope=openid+email+profile&service=lso&state=dfjtgpxO8h1eS83EqakZj + - generic [ref=e31]: + - button "Next" [ref=e33] + - link "Create account" [ref=e35] [cursor=pointer]: + - /url: /lifecycle/flows/signup?app_domain=https://o.alogins.net&client_id=225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com&code_challenge=oJlG0iJD7GEnZ_p0tMbi56r9QGirq6lY0KHNKh-A7sI&code_challenge_method=S256&continue=https://accounts.google.com/signin/oauth/legacy/consent?authuser%3Dunknown%26part%3DAJi8hAP_s0wcqLhX3B4DTcLADDDkyjYYD_dTsSJST_xu2o-PkobLfbuk1XhXVndyBN6gkOnR0zh89fZIeMovlOB4w8i9PC5L8hRlhSDi_OSh3ki0cAZ8RRH7CMPl0NmSZbAb7253b7Sq7Uj7dN8TmsRtXQbgjYmbhyQtpViFok9UeZM7XROiV83I_xwzDvOMQD1WQkkCPL_ZjRyGIpPgmLbBXxUWwGnWs7x0CLlb2wOYMM4diy8wjIIVzACtLq0g_hnnf0y_mxrQYevSjMx1y6vLEeMZrKz4zXxSwX11OP6adWx8v9lVviJvM53GJLq4oV46GDTGcxuXLkt9W6FBgRJqMoh1oulT8tHVf1O4VG6FuQkvXnppbkH8b9OMEnqTaVlL1DVwPrvaEytsqZ79DQ74hKi9NiK3RE9wkvTaSElEARWCxILbbRjXR-GKwwybfKjQwGUZ9t2sYcJdZK3ygn8vZIYDrPIKQM8g27tJTfNj5yjjYJZsv-EMRSSvheUtOMdNBzy7fqqBKvxGQEO3iDfgy88NdOrw1AktvipSuf5E5uVlJ5KPLTq5J8TuKHO9TQcmBu9Fn1U1_NwlvMkvWbPJ2zbkshNe2q200XCnKF6Wz1bLG7sukKzEoyJkmc3x7poz1z9JQ4f7%26flowName%3DGeneralOAuthFlow%26as%3DS356240196%253A1776175595013373%26client_id%3D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%23&dsh=S356240196:1776175595013373&flowEntry=SignUp&flowName=GlifWebSignIn&o2v=2&opparams=%253F&rart=ANgoxceHU_HzI34dur-e3VKjuSW_62nNyS0F-NAT8vowVRgzLCH8LgeU-dR_jmgEfEI3TjNPYuzeB6EBCMum_GguMnKcbkqUwFjfpff8YscBkT3joDYra5Q&redirect_uri=https://o.alogins.net/api/auth/callback&response_type=code&scope=openid+email+profile&service=lso&signInUrl=https://accounts.google.com/signin/oauth?app_domain%3Dhttps://o.alogins.net%26client_id%3D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%26code_challenge%3DoJlG0iJD7GEnZ_p0tMbi56r9QGirq6lY0KHNKh-A7sI%26code_challenge_method%3DS256%26continue%3Dhttps://accounts.google.com/signin/oauth/legacy/consent?authuser%253Dunknown%2526part%253DAJi8hAP_s0wcqLhX3B4DTcLADDDkyjYYD_dTsSJST_xu2o-PkobLfbuk1XhXVndyBN6gkOnR0zh89fZIeMovlOB4w8i9PC5L8hRlhSDi_OSh3ki0cAZ8RRH7CMPl0NmSZbAb7253b7Sq7Uj7dN8TmsRtXQbgjYmbhyQtpViFok9UeZM7XROiV83I_xwzDvOMQD1WQkkCPL_ZjRyGIpPgmLbBXxUWwGnWs7x0CLlb2wOYMM4diy8wjIIVzACtLq0g_hnnf0y_mxrQYevSjMx1y6vLEeMZrKz4zXxSwX11OP6adWx8v9lVviJvM53GJLq4oV46GDTGcxuXLkt9W6FBgRJqMoh1oulT8tHVf1O4VG6FuQkvXnppbkH8b9OMEnqTaVlL1DVwPrvaEytsqZ79DQ74hKi9NiK3RE9wkvTaSElEARWCxILbbRjXR-GKwwybfKjQwGUZ9t2sYcJdZK3ygn8vZIYDrPIKQM8g27tJTfNj5yjjYJZsv-EMRSSvheUtOMdNBzy7fqqBKvxGQEO3iDfgy88NdOrw1AktvipSuf5E5uVlJ5KPLTq5J8TuKHO9TQcmBu9Fn1U1_NwlvMkvWbPJ2zbkshNe2q200XCnKF6Wz1bLG7sukKzEoyJkmc3x7poz1z9JQ4f7%2526flowName%253DGeneralOAuthFlow%2526as%253DS356240196%25253A1776175595013373%2526client_id%253D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%2523%26dsh%3DS356240196:1776175595013373%26flowName%3DGeneralOAuthLite%26o2v%3D2%26opparams%3D%25253F%26rart%3DANgoxceHU_HzI34dur-e3VKjuSW_62nNyS0F-NAT8vowVRgzLCH8LgeU-dR_jmgEfEI3TjNPYuzeB6EBCMum_GguMnKcbkqUwFjfpff8YscBkT3joDYra5Q%26redirect_uri%3Dhttps://o.alogins.net/api/auth/callback%26response_type%3Dcode%26scope%3Dopenid%2Bemail%2Bprofile%26service%3Dlso%26state%3DdfjtgpxO8h1eS83EqakZj&state=dfjtgpxO8h1eS83EqakZj + - contentinfo [ref=e36]: + - combobox [ref=e39] [cursor=pointer]: + - option "Afrikaans" + - option "azərbaycan" + - option "bosanski" + - option "català" + - option "Čeština" + - option "Cymraeg" + - option "Dansk" + - option "Deutsch" + - option "eesti" + - option "English (United Kingdom)" + - option "English (United States)" [selected] + - option "Español (España)" + - option "Español (Latinoamérica)" + - option "euskara" + - option "Filipino" + - option "Français (Canada)" + - option "Français (France)" + - option "Gaeilge" + - option "galego" + - option "Hrvatski" + - option "Indonesia" + - option "isiZulu" + - option "íslenska" + - option "Italiano" + - option "Kiswahili" + - option "latviešu" + - option "lietuvių" + - option "magyar" + - option "Melayu" + - option "Nederlands" + - option "norsk" + - option "o‘zbek" + - option "polski" + - option "Português (Brasil)" + - option "Português (Portugal)" + - option "română" + - option "shqip" + - option "Slovenčina" + - option "slovenščina" + - option "srpski (latinica)" + - option "Suomi" + - option "Svenska" + - option "Tiếng Việt" + - option "Türkçe" + - option "Ελληνικά" + - option "беларуская" + - option "български" + - option "кыргызча" + - option "қазақ тілі" + - option "македонски" + - option "монгол" + - option "Русский" + - option "српски (ћирилица)" + - option "Українська" + - option "ქართული" + - option "հայերեն" + - option "‫עברית‬‎" + - option "‫اردو‬‎" + - option "‫العربية‬‎" + - option "‫فارسی‬‎" + - option "አማርኛ" + - option "नेपाली" + - option "मराठी" + - option "हिन्दी" + - option "অসমীয়া" + - option "বাংলা" + - option "ਪੰਜਾਬੀ" + - option "ગુજરાતી" + - option "ଓଡ଼ିଆ" + - option "தமிழ்" + - option "తెలుగు" + - option "ಕನ್ನಡ" + - option "മലയാളം" + - option "සිංහල" + - option "ไทย" + - option "ລາວ" + - option "မြန်မာ" + - option "ខ្មែរ" + - option "한국어" + - option "中文(香港)" + - option "日本語" + - option "简体中文" + - option "繁體中文" + - list [ref=e40]: + - listitem [ref=e41]: + - link "Help" [ref=e42] [cursor=pointer]: + - /url: https://support.google.com/accounts?hl=en-US&p=account_iph + - listitem [ref=e43]: + - link "Privacy" [ref=e44] [cursor=pointer]: + - /url: https://accounts.google.com/TOS?loc=LV&hl=en-US&privacy=true + - listitem [ref=e45]: + - link "Terms" [ref=e46] [cursor=pointer]: + - /url: https://accounts.google.com/TOS?loc=LV&hl=en-US \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-14T14-12-07-158Z.yml b/.playwright-mcp/page-2026-04-14T14-12-07-158Z.yml new file mode 100644 index 0000000..2ebe413 --- /dev/null +++ b/.playwright-mcp/page-2026-04-14T14-12-07-158Z.yml @@ -0,0 +1,16 @@ +- main [ref=e2]: + - generic [ref=e3]: + - heading "oO" [level=1] [ref=e4] + - paragraph [ref=e5]: one tip. right now. + - link "Continue with Google" [ref=e7] [cursor=pointer]: + - /url: /api/auth/login?redirectTo=/connect + - img [ref=e8] + - text: Continue with Google + - paragraph [ref=e13]: + - text: By continuing you agree to our + - link "Terms" [ref=e14] [cursor=pointer]: + - /url: /legal/terms + - text: and + - link "Privacy Policy" [ref=e15] [cursor=pointer]: + - /url: /legal/privacy + - text: . \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-14T14-12-17-872Z.yml b/.playwright-mcp/page-2026-04-14T14-12-17-872Z.yml new file mode 100644 index 0000000..368a768 --- /dev/null +++ b/.playwright-mcp/page-2026-04-14T14-12-17-872Z.yml @@ -0,0 +1,2 @@ +- main [ref=e2] [cursor=pointer]: + - generic [ref=e3]: ··· \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-14T14-14-53-788Z.yml b/.playwright-mcp/page-2026-04-14T14-14-53-788Z.yml new file mode 100644 index 0000000..2ebe413 --- /dev/null +++ b/.playwright-mcp/page-2026-04-14T14-14-53-788Z.yml @@ -0,0 +1,16 @@ +- main [ref=e2]: + - generic [ref=e3]: + - heading "oO" [level=1] [ref=e4] + - paragraph [ref=e5]: one tip. right now. + - link "Continue with Google" [ref=e7] [cursor=pointer]: + - /url: /api/auth/login?redirectTo=/connect + - img [ref=e8] + - text: Continue with Google + - paragraph [ref=e13]: + - text: By continuing you agree to our + - link "Terms" [ref=e14] [cursor=pointer]: + - /url: /legal/terms + - text: and + - link "Privacy Policy" [ref=e15] [cursor=pointer]: + - /url: /legal/privacy + - text: . \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-14T14-26-57-754Z.yml b/.playwright-mcp/page-2026-04-14T14-26-57-754Z.yml new file mode 100644 index 0000000..50f74af --- /dev/null +++ b/.playwright-mcp/page-2026-04-14T14-26-57-754Z.yml @@ -0,0 +1,119 @@ +- generic [ref=e3]: + - generic [ref=e5]: + - generic [ref=e8]: + - img "Google" [ref=e10] + - generic [ref=e11]: Sign in with Google + - generic [ref=e12]: + - generic [ref=e14]: + - heading "Sign in" [level=1] [ref=e15] + - paragraph [ref=e16]: + - text: to continue to + - button "alogins.net" [ref=e17] [cursor=pointer] + - generic [ref=e18]: + - generic [ref=e21]: + - generic [ref=e26]: + - textbox "Email or phone" [active] [ref=e27] + - generic: + - generic: Email or phone + - paragraph [ref=e28]: + - link "Forgot email?" [ref=e29] [cursor=pointer]: + - /url: /signin/v2/usernamerecovery?app_domain=https://o.alogins.net&client_id=225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com&code_challenge=-BqTqiuiRm7bqR18AN6dGJza3m1LQ-rUHm5iCKVp4L0&code_challenge_method=S256&continue=https://accounts.google.com/signin/oauth/legacy/consent?authuser%3Dunknown%26part%3DAJi8hAMZa_8Uw5oeDBf5xu6LwYAzWw0IfUPVe1s-RdkhKrryVpbj5DP1e4mWD5shlmUM9MHWJjmo0221X4Itv9m_QVhq6U9AE3ixMmFjYikcxLUbYpSC0ZK2Gpk6iXyS0bmfDCxbgrB-XxcJUfHUxxHIFAIPwGNH1HXRh9xm5nfY7qXSpWvjqH2SjPsvABBxBfb4_gYQVYDpFH6xY9tvo9ivQm607DUHzOGvM91l2PAzDK2xfzP1ly9SqBaA342VjnFJmEA5mKtYKfGXiThy7J62jQMM-NK8pjUTysf6PXNOLLyUCtl7VjQPs23EBAwe_22hjTKkVo9DRb9dlv8VNmIdVK-BVUoalJmfsRs3BVet5yibkeKV20QKQlCDgtPLCorYZyu3gnFh5taleK1WBbKLyRtscF3rVnhCkIp4Y4y3m8nHtTr_lKRi0jyIfZA9CJwxJnFJa50DFwjmiOYWosdQsuu6HCZ5CfNfCorlKIYB3zjmMRcFHdwYxPvydfXXR6OPui9JQfcE4KEjnE4sDQbB6B70TD9R-o7lqt5V9Qh0cOWwKpO0-m167gCqNjS67_qgdM4UK0vGResYyPoAGae9OtyQmCAj_dcU-62wi6Keit4fc9kh4tW_Sg3z-_uWIv3YDam93LJE%26flowName%3DGeneralOAuthFlow%26as%3DS-1308179881%253A1776176817375272%26client_id%3D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%23&dsh=S-1308179881:1776176817375272&flowName=GeneralOAuthLite&o2v=2&opparams=%253F&rart=ANgoxceTKJUOKU3v1dqvsh5ic8iCtLsW59TMJ-d2ocODSbnDkgr7QsEsYbgBLhyzyxlCKvCeKxeWXE4oh50Ic8Zii472KjuAo007j0Fg5aey109I_iJ5RME&redirect_uri=https://o.alogins.net/api/auth/callback&response_type=code&scope=openid+email+profile&service=lso&state=8jVx7mQ1bRb8HljdpHf35 + - generic [ref=e31]: + - button "Next" [ref=e33] + - link "Create account" [ref=e35] [cursor=pointer]: + - /url: /lifecycle/flows/signup?app_domain=https://o.alogins.net&client_id=225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com&code_challenge=-BqTqiuiRm7bqR18AN6dGJza3m1LQ-rUHm5iCKVp4L0&code_challenge_method=S256&continue=https://accounts.google.com/signin/oauth/legacy/consent?authuser%3Dunknown%26part%3DAJi8hAMZa_8Uw5oeDBf5xu6LwYAzWw0IfUPVe1s-RdkhKrryVpbj5DP1e4mWD5shlmUM9MHWJjmo0221X4Itv9m_QVhq6U9AE3ixMmFjYikcxLUbYpSC0ZK2Gpk6iXyS0bmfDCxbgrB-XxcJUfHUxxHIFAIPwGNH1HXRh9xm5nfY7qXSpWvjqH2SjPsvABBxBfb4_gYQVYDpFH6xY9tvo9ivQm607DUHzOGvM91l2PAzDK2xfzP1ly9SqBaA342VjnFJmEA5mKtYKfGXiThy7J62jQMM-NK8pjUTysf6PXNOLLyUCtl7VjQPs23EBAwe_22hjTKkVo9DRb9dlv8VNmIdVK-BVUoalJmfsRs3BVet5yibkeKV20QKQlCDgtPLCorYZyu3gnFh5taleK1WBbKLyRtscF3rVnhCkIp4Y4y3m8nHtTr_lKRi0jyIfZA9CJwxJnFJa50DFwjmiOYWosdQsuu6HCZ5CfNfCorlKIYB3zjmMRcFHdwYxPvydfXXR6OPui9JQfcE4KEjnE4sDQbB6B70TD9R-o7lqt5V9Qh0cOWwKpO0-m167gCqNjS67_qgdM4UK0vGResYyPoAGae9OtyQmCAj_dcU-62wi6Keit4fc9kh4tW_Sg3z-_uWIv3YDam93LJE%26flowName%3DGeneralOAuthFlow%26as%3DS-1308179881%253A1776176817375272%26client_id%3D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%23&dsh=S-1308179881:1776176817375272&flowEntry=SignUp&flowName=GlifWebSignIn&o2v=2&opparams=%253F&rart=ANgoxceTKJUOKU3v1dqvsh5ic8iCtLsW59TMJ-d2ocODSbnDkgr7QsEsYbgBLhyzyxlCKvCeKxeWXE4oh50Ic8Zii472KjuAo007j0Fg5aey109I_iJ5RME&redirect_uri=https://o.alogins.net/api/auth/callback&response_type=code&scope=openid+email+profile&service=lso&signInUrl=https://accounts.google.com/signin/oauth?app_domain%3Dhttps://o.alogins.net%26client_id%3D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%26code_challenge%3D-BqTqiuiRm7bqR18AN6dGJza3m1LQ-rUHm5iCKVp4L0%26code_challenge_method%3DS256%26continue%3Dhttps://accounts.google.com/signin/oauth/legacy/consent?authuser%253Dunknown%2526part%253DAJi8hAMZa_8Uw5oeDBf5xu6LwYAzWw0IfUPVe1s-RdkhKrryVpbj5DP1e4mWD5shlmUM9MHWJjmo0221X4Itv9m_QVhq6U9AE3ixMmFjYikcxLUbYpSC0ZK2Gpk6iXyS0bmfDCxbgrB-XxcJUfHUxxHIFAIPwGNH1HXRh9xm5nfY7qXSpWvjqH2SjPsvABBxBfb4_gYQVYDpFH6xY9tvo9ivQm607DUHzOGvM91l2PAzDK2xfzP1ly9SqBaA342VjnFJmEA5mKtYKfGXiThy7J62jQMM-NK8pjUTysf6PXNOLLyUCtl7VjQPs23EBAwe_22hjTKkVo9DRb9dlv8VNmIdVK-BVUoalJmfsRs3BVet5yibkeKV20QKQlCDgtPLCorYZyu3gnFh5taleK1WBbKLyRtscF3rVnhCkIp4Y4y3m8nHtTr_lKRi0jyIfZA9CJwxJnFJa50DFwjmiOYWosdQsuu6HCZ5CfNfCorlKIYB3zjmMRcFHdwYxPvydfXXR6OPui9JQfcE4KEjnE4sDQbB6B70TD9R-o7lqt5V9Qh0cOWwKpO0-m167gCqNjS67_qgdM4UK0vGResYyPoAGae9OtyQmCAj_dcU-62wi6Keit4fc9kh4tW_Sg3z-_uWIv3YDam93LJE%2526flowName%253DGeneralOAuthFlow%2526as%253DS-1308179881%25253A1776176817375272%2526client_id%253D225787180325-cesuikl95j1qg3aijh4j10n8n7usf65p.apps.googleusercontent.com%2523%26dsh%3DS-1308179881:1776176817375272%26flowName%3DGeneralOAuthLite%26o2v%3D2%26opparams%3D%25253F%26rart%3DANgoxceTKJUOKU3v1dqvsh5ic8iCtLsW59TMJ-d2ocODSbnDkgr7QsEsYbgBLhyzyxlCKvCeKxeWXE4oh50Ic8Zii472KjuAo007j0Fg5aey109I_iJ5RME%26redirect_uri%3Dhttps://o.alogins.net/api/auth/callback%26response_type%3Dcode%26scope%3Dopenid%2Bemail%2Bprofile%26service%3Dlso%26state%3D8jVx7mQ1bRb8HljdpHf35&state=8jVx7mQ1bRb8HljdpHf35 + - contentinfo [ref=e36]: + - combobox [ref=e39] [cursor=pointer]: + - option "Afrikaans" + - option "azərbaycan" + - option "bosanski" + - option "català" + - option "Čeština" + - option "Cymraeg" + - option "Dansk" + - option "Deutsch" + - option "eesti" + - option "English (United Kingdom)" + - option "English (United States)" [selected] + - option "Español (España)" + - option "Español (Latinoamérica)" + - option "euskara" + - option "Filipino" + - option "Français (Canada)" + - option "Français (France)" + - option "Gaeilge" + - option "galego" + - option "Hrvatski" + - option "Indonesia" + - option "isiZulu" + - option "íslenska" + - option "Italiano" + - option "Kiswahili" + - option "latviešu" + - option "lietuvių" + - option "magyar" + - option "Melayu" + - option "Nederlands" + - option "norsk" + - option "o‘zbek" + - option "polski" + - option "Português (Brasil)" + - option "Português (Portugal)" + - option "română" + - option "shqip" + - option "Slovenčina" + - option "slovenščina" + - option "srpski (latinica)" + - option "Suomi" + - option "Svenska" + - option "Tiếng Việt" + - option "Türkçe" + - option "Ελληνικά" + - option "беларуская" + - option "български" + - option "кыргызча" + - option "қазақ тілі" + - option "македонски" + - option "монгол" + - option "Русский" + - option "српски (ћирилица)" + - option "Українська" + - option "ქართული" + - option "հայերեն" + - option "‫עברית‬‎" + - option "‫اردو‬‎" + - option "‫العربية‬‎" + - option "‫فارسی‬‎" + - option "አማርኛ" + - option "नेपाली" + - option "मराठी" + - option "हिन्दी" + - option "অসমীয়া" + - option "বাংলা" + - option "ਪੰਜਾਬੀ" + - option "ગુજરાતી" + - option "ଓଡ଼ିଆ" + - option "தமிழ்" + - option "తెలుగు" + - option "ಕನ್ನಡ" + - option "മലയാളം" + - option "සිංහල" + - option "ไทย" + - option "ລາວ" + - option "မြန်မာ" + - option "ខ្មែរ" + - option "한국어" + - option "中文(香港)" + - option "日本語" + - option "简体中文" + - option "繁體中文" + - list [ref=e40]: + - listitem [ref=e41]: + - link "Help" [ref=e42] [cursor=pointer]: + - /url: https://support.google.com/accounts?hl=en-US&p=account_iph + - listitem [ref=e43]: + - link "Privacy" [ref=e44] [cursor=pointer]: + - /url: https://accounts.google.com/TOS?loc=LV&hl=en-US&privacy=true + - listitem [ref=e45]: + - link "Terms" [ref=e46] [cursor=pointer]: + - /url: https://accounts.google.com/TOS?loc=LV&hl=en-US \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-15T07-41-23-867Z.yml b/.playwright-mcp/page-2026-04-15T07-41-23-867Z.yml new file mode 100644 index 0000000..2ebe413 --- /dev/null +++ b/.playwright-mcp/page-2026-04-15T07-41-23-867Z.yml @@ -0,0 +1,16 @@ +- main [ref=e2]: + - generic [ref=e3]: + - heading "oO" [level=1] [ref=e4] + - paragraph [ref=e5]: one tip. right now. + - link "Continue with Google" [ref=e7] [cursor=pointer]: + - /url: /api/auth/login?redirectTo=/connect + - img [ref=e8] + - text: Continue with Google + - paragraph [ref=e13]: + - text: By continuing you agree to our + - link "Terms" [ref=e14] [cursor=pointer]: + - /url: /legal/terms + - text: and + - link "Privacy Policy" [ref=e15] [cursor=pointer]: + - /url: /legal/privacy + - text: . \ No newline at end of file diff --git a/.playwright-mcp/page-2026-04-15T08-09-40-643Z.yml b/.playwright-mcp/page-2026-04-15T08-09-40-643Z.yml new file mode 100644 index 0000000..2ebe413 --- /dev/null +++ b/.playwright-mcp/page-2026-04-15T08-09-40-643Z.yml @@ -0,0 +1,16 @@ +- main [ref=e2]: + - generic [ref=e3]: + - heading "oO" [level=1] [ref=e4] + - paragraph [ref=e5]: one tip. right now. + - link "Continue with Google" [ref=e7] [cursor=pointer]: + - /url: /api/auth/login?redirectTo=/connect + - img [ref=e8] + - text: Continue with Google + - paragraph [ref=e13]: + - text: By continuing you agree to our + - link "Terms" [ref=e14] [cursor=pointer]: + - /url: /legal/terms + - text: and + - link "Privacy Policy" [ref=e15] [cursor=pointer]: + - /url: /legal/privacy + - text: . \ No newline at end of file diff --git a/apps/web/src/app/connect/page.tsx b/apps/web/src/app/connect/page.tsx index ce70199..59d1bf7 100644 --- a/apps/web/src/app/connect/page.tsx +++ b/apps/web/src/app/connect/page.tsx @@ -2,7 +2,7 @@ import { useEffect, useState, useCallback } from 'react'; import { useSearchParams } from 'next/navigation'; -import { getIntegrations, disconnectIntegration } from '@/lib/api'; +import { getIntegrations, disconnectIntegration, deleteAccount, logout } from '@/lib/api'; import type { Integration } from '@oo/shared-types'; import { Suspense } from 'react'; @@ -11,6 +11,7 @@ function ConnectPageInner() { const [integrations, setIntegrations] = useState([]); const [loading, setLoading] = useState(true); const [disconnecting, setDisconnecting] = useState(null); + const [deleting, setDeleting] = useState(false); const load = useCallback(async () => { const { integrations: list } = await getIntegrations(); @@ -26,6 +27,14 @@ function ConnectPageInner() { const isConnected = (provider: string) => integrations.some((i) => i.provider === provider && i.status === 'connected'); + const handleDeleteAccount = async () => { + if (!confirm('Delete your account? This cannot be undone.')) return; + setDeleting(true); + await deleteAccount(); + await logout(); + window.location.href = '/sign-in'; + }; + const handleDisconnect = async (provider: string) => { setDisconnecting(provider); await disconnectIntegration(provider); @@ -140,6 +149,23 @@ function ConnectPageInner() { )} + +
+ +
); } diff --git a/apps/web/src/app/legal/privacy/page.tsx b/apps/web/src/app/legal/privacy/page.tsx new file mode 100644 index 0000000..f5fea3b --- /dev/null +++ b/apps/web/src/app/legal/privacy/page.tsx @@ -0,0 +1,41 @@ +export default function Privacy() { + return ( +
+

Privacy Policy

+ +

Effective: 1 April 2026

+ +
+

What we collect

+
    +
  • Your Google account email, name, and profile picture — to identify you.
  • +
  • OAuth tokens for integrations you explicitly connect.
  • +
  • Your reactions to tips (done / snooze / dismiss) — to improve recommendations.
  • +
+
+ +
+

What we don't collect

+

+ We do not copy your tasks, calendar events, or any third-party app content into our database. Data is fetched on demand and held in memory for at most 30 seconds. +

+
+ +
+

How we use it

+

+ Solely to operate the recommendation engine. We do not sell data, share it with third parties, or use it for advertising. +

+
+ +
+

Your rights

+

+ You can disconnect any integration at any time from the Connect page. You can delete your account, which permanently purges all stored data. Contact the owner for data export requests. +

+
+ + ← Back +
+ ); +} diff --git a/apps/web/src/app/legal/terms/page.tsx b/apps/web/src/app/legal/terms/page.tsx new file mode 100644 index 0000000..66f65b7 --- /dev/null +++ b/apps/web/src/app/legal/terms/page.tsx @@ -0,0 +1,39 @@ +export default function Terms() { + return ( +
+

Terms of Service

+ +

Effective: 1 April 2026

+ +
+

1. The service

+

+ oO is a personal recommendation system. It reads signals from apps you connect and surfaces one tip at a time. The service is provided as-is during the prototype phase. +

+
+ +
+

2. Your data

+

+ We store OAuth tokens for integrations you connect. We fetch your tasks on demand — we do not copy or cache raw data beyond a 30-second in-memory buffer. You can revoke access or delete your account at any time. +

+
+ +
+

3. Account deletion

+

+ Deleting your account revokes all integration tokens, purges your feedback history, and anonymises your identity record. No data is retained in identifiable form. +

+
+ +
+

4. Limitations

+

+ This is a prototype. We make no uptime guarantees. The service may change or be discontinued with reasonable notice. +

+
+ + ← Back +
+ ); +} diff --git a/apps/web/src/app/tip/page.tsx b/apps/web/src/app/tip/page.tsx index ab34276..09f3b0c 100644 --- a/apps/web/src/app/tip/page.tsx +++ b/apps/web/src/app/tip/page.tsx @@ -88,6 +88,7 @@ export default function TipPage() { return ( <> +