feat: migrate company verification from Retool to private APIs#3930
Merged
idoshamun merged 2 commits intoJun 7, 2026
Merged
Conversation
Migrate the three Retool company-verification write actions to service-only private REST endpoints under /p/company-verification: - POST /companies: create a company, re-hosting the logo on Cloudinary via uploadLogoFromUrl and generating a short id when omitted. - POST /link-domain: link user_company rows to a company by email domain (404 when the company is missing). - POST /reject-domain: set flags.rejected on matching rows. Domains/inputs are normalized (trim + lowercase) and matched against split_part(lower(email), '@', 2) so stored-email casing cannot cause missed matches. Includes Zod validation and integration tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Code review follow-ups: - POST /company-verification/companies now returns 409 when a caller supplies an id that already exists, instead of silently upserting (Company ids are referenced by user_company.companyId, so overwriting an existing company is destructive). The conflict is checked before the Cloudinary upload to avoid wasted work. - Extract the duplicated parseSchema helper into src/routes/private/utils.ts and import it from both contributions and companyVerification routers (CLAUDE.md single-source-of-truth guidance). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🍹 The Update (preview) for dailydotdev/api/prod (at d24120b) was successful. ✨ Neo Code ReviewRoutine deployment of a new internal company-verification API route and a minor utility refactor; database and Clickhouse migration jobs run as part of the standard deploy process. ✅ Low RiskThis is a routine code deployment rolling out commit The migration jobs (both DB and Clickhouse) are being recycled as expected — old jobs tied to the previous commit hash are deleted and new ones for the current commit are created. Resource Changes Name Type Operation
~ vpc-native-validate-active-users-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-history-day-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-rotate-weekly-quests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-worker-job-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-post-lifecycle-state-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-highlighted-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-opportunities-cron kubernetes:batch/v1:CronJob update
~ vpc-native-hourly-notification-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-source-public-threshold-cron kubernetes:batch/v1:CronJob update
~ vpc-native-rotate-daily-quests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-calculate-top-readers-cron kubernetes:batch/v1:CronJob update
~ vpc-native-expire-super-agent-trial-cron kubernetes:batch/v1:CronJob update
~ vpc-native-bg-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-deployment kubernetes:apps/v1:Deployment update
+ vpc-native-api-clickhouse-migration-9888a4ca kubernetes:batch/v1:Job create
~ vpc-native-personalized-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-temporal-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-ws-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-clean-gifted-plus-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-analytics-history-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-sync-subscription-with-cio-cron kubernetes:batch/v1:CronJob update
~ vpc-native-check-analytics-report-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-current-streak-cron kubernetes:batch/v1:CronJob update
~ vpc-native-generate-search-invites-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-channel-highlights-cron kubernetes:batch/v1:CronJob update
~ vpc-native-daily-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-materialize-yearly-best-post-archives-cron kubernetes:batch/v1:CronJob update
- vpc-native-api-clickhouse-migration-26b0e1ee kubernetes:batch/v1:Job delete
+ vpc-native-api-db-migration-9888a4ca kubernetes:batch/v1:Job create
~ vpc-native-clean-zombie-images-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-user-companies-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-tag-materialized-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-users-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-achievement-rarity-cron kubernetes:batch/v1:CronJob update
~ vpc-native-materialize-monthly-best-post-archives-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-channel-highlights-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-updated-sync-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-expired-better-auth-sessions-cron kubernetes:batch/v1:CronJob update
~ vpc-native-private-deployment kubernetes:apps/v1:Deployment update
... and 13 other changes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the Retool company-verification write actions with service-only private REST endpoints in daily-api, so the review workflow can be driven by AI agents (and humans) through a stable, validated API instead of raw SQL. Read/listing queries are out of scope.
Endpoints (under
/p/company-verification)POST /companies— create a company. Generates theidviagenerateShortId()when not supplied; uploads the providedimageURL to Cloudinary (uploadLogoFromUrl) and stores the hosted URL; normalizes domains. Returns201.POST /link-domain— linkuser_companyrows to a company by email domain (404if the company doesn't exist). Returns affected-row count.POST /reject-domain— setflags.rejected = truefor matching rows viaupdateFlagsStatement. Idempotent. Returns affected-row count.Key decisions
contributions.ts— the closest existing private-router pattern:preHandlerservice guard (404 when!req.service), Zod-validated bodies, query-builder access, handlers that alwaysreturn res.send(...)..trim().toLowerCase()'d in Zod and matched againstsplit_part(lower(email), '@', 2)(parameterized, no rawcon.query), so stored-email casing can't cause missed matches — a deliberate improvement over Retool's exact match.idreturns409instead of silently upserting, since company ids are referenced byuser_company.companyId.Shared
parseSchemahelper extracted tosrc/routes/private/utils.tsand reused by bothcontributionsandcompanyVerification.Tests
Integration tests in
__tests__/routes/private/companyVerification.ts(Cloudinary mocked): service guards, create (generated/provided id, hosted image, domain normalization, validation, 409 conflict), link (mixed-case matching, 404), reject (mixed-case, idempotency).Closes ENG-1630
Created by Huginn 🐦⬛