Skip to content

feat(profile): add contributor profiles - #1082

Open
klnwlks wants to merge 63 commits into
sveltekit-rewritefrom
contributor-profiles
Open

feat(profile): add contributor profiles#1082
klnwlks wants to merge 63 commits into
sveltekit-rewritefrom
contributor-profiles

Conversation

@klnwlks

@klnwlks klnwlks commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds account-backed public contributor profiles at /contributor/[slug].
  • Adds strict social-link validation, per-link privacy, messaging disclosure, and optimistic owner updates.
  • Adds immutable profile audits and admin hide, restore, unsafe-link, and avatar-reference controls.
  • Routes landing credits and entity-photo attribution through the shared resolver.
  • Adds the additive schema migration, deterministic active-account backfill, account provisioning, documentation, and PGlite artifact refresh.

Closes #310

Verification

  • bun run check: 0 errors.
  • Focused profile, attribution, moderation, UI, and PGlite tests: 11 files, 38 tests passed.
  • bun run db:generate: no pending schema changes.
  • Targeted Biome checks: passed.
  • git diff --check: passed.
  • Full unit suite: 193 test files passed. Four unrelated campus-gate tests fail because their expected src/... assets are absent.
  • Migration application, production build, and live SSR browser verification require DATABASE_URL, which is not configured in this workspace.
  • Full repository lint remains blocked by existing repo-wide .cursor diagnostics.

@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
saan-ang-room Ready Ready Preview Aug 31, 2026 12:48pm

Request Review

name,
profileUrl: validatedProfileUrl(account.profileUrl),
};
const attribution = await resolveContributorAttribution(userId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolveContributorAttribution no longer checks showInCredits (it only gates on isPublic/isModeratorHidden/isActive/deletedAt, see contributor-profile.ts resolveContributorAttribution). The old code here explicitly required account.showInCredits before returning a profile URL. Now a contributor who turns off "show in credits" (but leaves the profile public) will still have their photo attributions link to /contributor/<slug>attributionProfileUrl is rendered publicly in EntityPhotoGallery.svelte/BuildingResult.svelte. This contradicts CONTRIBUTING.md: "Credits visibility is separate from profile visibility. Turning credits off removes the account from public contributor credits without deleting the profile." getEditorCredits() is safe because its SQL already filters WHERE u.show_in_credits = true before calling this resolver, but photo attribution has no such filter.

});
if (!accountRes.ok) {
const accountData = (await accountRes.json().catch(() => ({}))) as { error?: string };
profileError = accountData.error ?? 'Profile saved, but account photo could not be saved.';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the avatar PATCH fails here, the function returns without calling setProfileDraft(data) (line 289), even though the PUT /api/contributors/me call right before it already committed the bio/visibility/social-link changes server-side and bumped version. The local contributorProfile.version stays stale, so the next save attempt will hit a 409 conflict purely because of this failure path, forcing the user to "Reload server profile" even though their own edit succeeded. Consider calling setProfileDraft(data as EditableProfile) before attempting the avatar PATCH, so local state tracks the version that was actually persisted.

@claude

claude Bot commented Aug 29, 2026

Copy link
Copy Markdown

Reviewed the contributor profiles feature. Two issues found, left as inline comments:

  1. Privacy regression: resolveContributorAttribution (contributor-profile.ts) dropped the showInCredits gate that the old resolvePhotoAttribution code had. Photo attribution links (attributionProfileUrl, rendered publicly in EntityPhotoGallery.svelte/BuildingResult.svelte) now only depend on profile isPublic, not showInCredits. A contributor who turns off "show in credits" while keeping their profile public will still be publicly linked from photo credits, contradicting the documented behavior in CONTRIBUTING.md that the two toggles are independent. getEditorCredits() is unaffected since its SQL already filters on show_in_credits before calling the resolver.

  2. Edge case / state desync: in AccountSettingsModal.svelte saveProfile(), if the profile PUT succeeds but the follow-up avatar PATCH to /api/account/me fails, the function returns before calling setProfileDraft(data). The already-committed version bump is never reflected locally, so the next save attempt spuriously 409s.

Rest of the change (auth checks on admin moderation routes, optimistic-concurrency version handling, URL/host allowlists for social links, rate limiting, audit trail) looks solid.

klnwlks added 24 commits August 29, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant