feat: add githubProfileTags and onboardingProfileTags mutations#3775
feat: add githubProfileTags and onboardingProfileTags mutations#3775
Conversation
Add two GraphQL mutations for onboarding v2 tag extraction via bragi: - githubProfileTags: reads GitHub token from ba_account, sends to bragi with full allowed keyword vocabulary, saves results as ContentPreference - onboardingProfileTags: sends free-text prompt to bragi, cross-matches results against allowed keywords, saves as ContentPreference Both mutations are idempotent — subsequent calls return saved tags without calling bragi. Rate limited to 3/hour. Tags persisted to both ContentPreferenceKeyword and FeedTag for backward compatibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🍹 The Update (preview) for dailydotdev/api/prod (at 6b3eb32) was successful. ✨ Neo ExplanationRoutine deployment of a new application version (commit `78d7df71`) across all services and cronjobs, with accompanying database and ClickHouse migration jobs. ✅ Low RiskThis is a standard application deployment rolling out commit The two migration Jobs (Postgres via TypeORM and ClickHouse) follow the expected pattern: old jobs keyed to the previous SHA are deleted and new jobs keyed to the new SHA are created to run migrations against the new image. The migrations run with The GCP provider credential warning is cosmetic and does not affect the Kubernetes resources being deployed. Resource Changes Name Type Operation
~ vpc-native-clean-gifted-plus-cron kubernetes:batch/v1:CronJob update
~ vpc-native-personalized-digest-deployment kubernetes:apps/v1:Deployment update
- vpc-native-api-clickhouse-migration-1e518d2a kubernetes:batch/v1:Job delete
~ vpc-native-update-source-public-threshold-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-expire-super-agent-trial-cron kubernetes:batch/v1:CronJob update
~ vpc-native-calculate-top-readers-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-updated-sync-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-posts-analytics-refresh-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-user-companies-cron kubernetes:batch/v1:CronJob update
~ vpc-native-materialize-yearly-best-post-archives-cron kubernetes:batch/v1:CronJob update
~ vpc-native-rotate-weekly-quests-cron kubernetes:batch/v1:CronJob update
+ vpc-native-api-clickhouse-migration-78d7df71 kubernetes:batch/v1:Job create
~ vpc-native-personalized-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-sync-subscription-with-cio-cron kubernetes:batch/v1:CronJob update
~ vpc-native-validate-active-users-cron kubernetes:batch/v1:CronJob update
~ vpc-native-channel-digests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-generic-referral-reminder-cron kubernetes:batch/v1:CronJob update
~ vpc-native-daily-digest-cron kubernetes:batch/v1:CronJob update
- vpc-native-api-db-migration-1e518d2a kubernetes:batch/v1:Job delete
~ vpc-native-update-achievement-rarity-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-hourly-notification-cron kubernetes:batch/v1:CronJob update
+ vpc-native-api-db-migration-78d7df71 kubernetes:batch/v1:Job create
~ vpc-native-update-tags-str-cron kubernetes:batch/v1:CronJob update
~ vpc-native-squad-posts-analytics-refresh-cron kubernetes:batch/v1:CronJob update
~ vpc-native-temporal-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-user-profile-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-bg-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-post-analytics-history-day-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-trending-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-opportunities-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-highlighted-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-users-cron kubernetes:batch/v1:CronJob update
~ vpc-native-private-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-rotate-daily-quests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-channel-highlights-cron kubernetes:batch/v1:CronJob update
~ vpc-native-generate-search-invites-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-tag-materialized-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-materialize-monthly-best-post-archives-cron kubernetes:batch/v1:CronJob update
... and 11 other changes |
|
@claude review |
|
Claude finished @capJavert's task in 2m 14s —— View job Code Review
Overall the feature is well-structured with good test coverage and correct use of proto message classes. There are a few issues to address. CriticalRaw SQL query violates codebase rules ( const result = await ctx.con.query(
`SELECT "accessToken" FROM ba_account WHERE "userId" = $1 AND "providerId" = 'github' LIMIT 1`,
[ctx.userId],
);CLAUDE.md explicitly says: "Never use raw SQL queries ( ImportantIdempotency check is too broad — conflates mutations and manual follows ( Both mutations check for any
There's no marker to distinguish "tags bootstrapped by this mutation" from "tags the user manually followed". Consider tracking this via a user flag (e.g., MinorZod validation runs after idempotency check ( // existing check first...
if (existing.length) {
return { includeTags: existing.map((pref) => pref.keywordId) };
}
// THEN validation
const parsed = onboardingProfileTagsInputSchema.parse(args);If a user has cached tags, an invalid prompt (e.g., empty string or 2000+ chars) would bypass validation silently. Validate first for consistent behavior. Fix this → Keyword vocabulary fetch uses primary DB ( Both
Code duplication in transaction block The TestsMissing test: Missing test: prompt max length — the test for empty prompt is good, but there is no test for a prompt exceeding the 2000-char limit. Nits
|
- Move Zod validation before idempotency check in onboardingProfileTags - Use queryReadReplica for keyword vocabulary fetches in both resolvers - Add take: 500 limit to onboardingProfileTags existing check - Remove unnecessary orderBy on vocabulary query - Add GQL docs describing one-shot + idempotent return behavior - Add test: onboardingProfileTags bragi NotFound error - Add test: prompt exceeding 2000-char max length Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Bump @dailydotdev/schema to 0.3.3 (adds tagVocabulary to OnboardingProfileTagsRequest) - Pass allowed keyword vocabulary to bragi onboardingProfileTags call - Remove post-hoc cross-match — bragi now constrains output via vocabulary - Update test: verify vocabulary is passed to bragi Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add two GraphQL mutations for onboarding v2 tag extraction via bragi:
Both mutations are idempotent — subsequent calls return saved tags without calling bragi. Rate limited to 3/hour. Tags persisted to both ContentPreferenceKeyword and FeedTag for backward compatibility.