9e3e59a804
One person could not work for two businesses, and signup and staff creation told anyone whether an email or phone was registered anywhere on the platform. - User email and phone are now unique per business: indexes on (businessId, email) and (businessId, phoneNumber). Duplicate checks in signup and branch-manager creation are scoped to the business, so they no longer reveal other businesses' users. - Login finds the email in every business and checks the password against each account. One match signs straight in; several return 300 with the businesses to choose from, and the login page shows a picker. A wrong password returns the same 401 as before and reveals nothing; failures count against each candidate account, and a correct password only resets the accounts it opens. - Platform-operator access now also needs a platformAdmin flag on the account. With per-business emails, an email match alone would have let any owner create a staff account with the operator's email and open the cross-tenant console. The flag is only set by the seed and the migration; removing the email from PLATFORM_ADMIN_EMAILS still revokes. - npm run migrate:identity flags today's operators (while each listed email still matches one account) and syncs the User indexes, dropping the old unique email_1 and phoneNumber_1. Checked against a database in the old shape; safe to re-run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
1.2 KiB
JSON
45 lines
1.2 KiB
JSON
{
|
|
"name": "aquaflow-web",
|
|
"version": "1.0.0",
|
|
"private": true,
|
|
"scripts": {
|
|
"dev": "next dev",
|
|
"build": "next build",
|
|
"start": "next start",
|
|
"lint": "next lint",
|
|
"seed": "tsx scripts/seed.ts",
|
|
"migrate:multitenant": "tsx scripts/migrate-multitenant.ts",
|
|
"test": "vitest run",
|
|
"typecheck": "tsc --noEmit",
|
|
"backfill:stock": "tsx scripts/backfill-stock-from-purchases.ts",
|
|
"migrate:identity": "tsx scripts/migrate-per-business-identity.ts"
|
|
},
|
|
"dependencies": {
|
|
"axios": "^1.7.7",
|
|
"bcryptjs": "^2.4.3",
|
|
"date-fns": "^3.6.0",
|
|
"idb": "^8.0.0",
|
|
"jsonwebtoken": "^9.0.2",
|
|
"mongoose": "^8.6.0",
|
|
"next": "^14.2.35",
|
|
"react": "^18.3.1",
|
|
"react-dom": "^18.3.1",
|
|
"zod": "^3.23.8"
|
|
},
|
|
"devDependencies": {
|
|
"@types/bcryptjs": "^2.4.6",
|
|
"@types/jsonwebtoken": "^9.0.6",
|
|
"@types/node": "^20.14.9",
|
|
"@types/react": "^18.3.3",
|
|
"@types/react-dom": "^18.3.0",
|
|
"autoprefixer": "^10.4.19",
|
|
"dotenv": "^16.4.5",
|
|
"mongodb-memory-server": "^10.1.4",
|
|
"postcss": "^8.4.39",
|
|
"tailwindcss": "^3.4.4",
|
|
"tsx": "^4.19.0",
|
|
"typescript": "^5.5.3",
|
|
"vitest": "^2.1.9"
|
|
}
|
|
}
|