Add public profile task assignment#85
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds owner-facing public-profile controls and privacy toggle, extracts a reusable CreateTaskDialog and PersonTaskAssignmentAction (with assignTask=1 auto-open), enforces person-profile visibility server-side with tests, updates Navbar/route links, refactors CampaignActionFab, revises visual-review tooling and PR preview packet + CI, updates magic-link email/messaging copy, adds Sentry preview auditing, and tweaks treaty slider UI and E2E expectations. ChangesPublic profiles and task assignment
Estimated code review effort 🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Pull request overview
This PR adds owner controls and task assignment to public profile pages. It introduces a privacy gate on getPersonTaskProfileData so private profiles are hidden from non-owners while still letting the owner view their own. The task creation form is extracted into a shared CreateTaskDialog component used by both the existing FAB and the new "Assign Task" action on a person's profile, with a signed-out flow that redirects to sign-in and auto-opens the dialog via ?assignTask=1 after login.
Changes:
- Add
isPublicselection and owner-only gate togetPersonTaskProfileData, with new unit tests for the private/owner cases. - Extract
CreateTaskDialogso it can be reused by the FAB and a newPersonTaskAssignmentActionon profile pages (with sign-in redirect + auto-open). - Add
PublicProfileOwnerControls(visibility toggle, share URL, view/edit links), wire it into/people/[id], add a public-profile link in the navbar side menu, and adjustPrivacyTogglestyling/disabled state.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/web/src/lib/tasks.server.ts | Select isPublic and gate private profiles from non-owners. |
| packages/web/src/lib/tests/tasks.server.test.ts | Tests for private/owner visibility behavior. |
| packages/web/src/components/tasks/CreateTaskDialog.tsx | New shared task creation dialog with optional fixed assignee and 401 sign-in redirect. |
| packages/web/src/components/site/CampaignActionFab.tsx | Refactored to use shared CreateTaskDialog. |
| packages/web/src/components/profile/PublicProfileOwnerControls.tsx | New owner-only profile controls (visibility, share URL, links). |
| packages/web/src/components/people/PersonTaskAssignmentAction.tsx | New action with sign-in fallback and auto-open via assignTask=1. |
| packages/web/src/components/Navbar.tsx | Adds public-profile link in the authenticated side menu. |
| packages/web/src/components/dashboard/PrivacyToggle.tsx | Becomes a button with disabled state; restyled. |
| packages/web/src/app/people/[id]/page.tsx | Renders owner controls and the assign-task action. |
| packages/web/e2e/visual-regression.spec.ts | Adds a load wait before screenshotting. |
| packages/web/e2e/utils/visual-routes.ts | New visual routes for owner view and assign dialog. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/web/src/components/Navbar.tsx`:
- Around line 80-82: Replace the manual people URL construction for
publicProfileHref with the shared helper: call getPersonHref(user) (from
`@/lib/person-href`) when user and user.personId exist instead of building
`${ROUTES.people}/${user.handle ?? user.personId}`; ensure getPersonHref is
imported and used in the publicProfileHref assignment (and remove or stop using
ROUTES.people for this case).
In `@packages/web/src/components/profile/PublicProfileOwnerControls.tsx`:
- Line 113: In PublicProfileOwnerControls replace the hardcoded Tailwind color
class on the error paragraph (the <p> rendering {error}) with the project
semantic error/destructive token class; locate the p with className "mt-2
text-sm font-bold text-red-700" and change "text-red-700" to the app’s semantic
error token (e.g., the project's destructive/error text utility) so the
component uses theme tokens instead of a hardcoded palette value.
In `@packages/web/src/components/tasks/CreateTaskDialog.tsx`:
- Around line 233-237: Cancel currently only calls onOpenChange(false) so the
form's local state persists; update the Button onClick handler to also reset the
dialog form state (e.g., call the form reset function) before closing.
Specifically, call the form reset helper used in this component (for example
form.reset() or reset()) and any error/field-clear helpers as needed, then call
onOpenChange(false) so the dialog closes with fresh values and no stale errors.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 15e48bd8-8393-441d-a24e-c38f5a4f1120
📒 Files selected for processing (11)
packages/web/e2e/utils/visual-routes.tspackages/web/e2e/visual-regression.spec.tspackages/web/src/app/people/[id]/page.tsxpackages/web/src/components/Navbar.tsxpackages/web/src/components/dashboard/PrivacyToggle.tsxpackages/web/src/components/people/PersonTaskAssignmentAction.tsxpackages/web/src/components/profile/PublicProfileOwnerControls.tsxpackages/web/src/components/site/CampaignActionFab.tsxpackages/web/src/components/tasks/CreateTaskDialog.tsxpackages/web/src/lib/__tests__/tasks.server.test.tspackages/web/src/lib/tasks.server.ts
Code reviewFour CLAUDE.md compliance issues found. No bugs or security issues. 1.
|
PR review packetStart here
Review checklist
Changed files considered
Updated automatically when this PR's preview or visual review reruns. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/web/e2e/smoke.spec.ts (1)
46-49: ⚡ Quick winReplace cookie-name magic strings with an enum.
Use an enum for these cookie names to match the TypeScript guideline and avoid hardcoded literals.
♻️ Proposed refactor
-const NEXT_AUTH_COOKIE_NAMES = [ - "next-auth.session-token", - "__Secure-next-auth.session-token", -]; +enum NextAuthCookieName { + SessionToken = "next-auth.session-token", + SecureSessionToken = "__Secure-next-auth.session-token", +} + +const NEXT_AUTH_COOKIE_NAMES: ReadonlyArray<NextAuthCookieName> = [ + NextAuthCookieName.SessionToken, + NextAuthCookieName.SecureSessionToken, +];As per coding guidelines,
**/*.{ts,tsx}: Use enums instead of magic strings in TypeScript code.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/e2e/smoke.spec.ts` around lines 46 - 49, Replace the hardcoded NEXT_AUTH_COOKIE_NAMES array with a TypeScript enum (e.g., NextAuthCookieName) that lists "NextAuthSessionToken" and "__SecureNextAuthSessionToken" (or similar descriptive enum keys) and then export an array of enum values to use where NEXT_AUTH_COOKIE_NAMES is referenced; update any usages of NEXT_AUTH_COOKIE_NAMES to reference the enum values (e.g., NextAuthCookieName.NextAuthSessionToken) to remove magic string literals and keep type safety while preserving the original string values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/web/e2e/smoke.spec.ts`:
- Around line 46-49: Replace the hardcoded NEXT_AUTH_COOKIE_NAMES array with a
TypeScript enum (e.g., NextAuthCookieName) that lists "NextAuthSessionToken" and
"__SecureNextAuthSessionToken" (or similar descriptive enum keys) and then
export an array of enum values to use where NEXT_AUTH_COOKIE_NAMES is
referenced; update any usages of NEXT_AUTH_COOKIE_NAMES to reference the enum
values (e.g., NextAuthCookieName.NextAuthSessionToken) to remove magic string
literals and keep type safety while preserving the original string values.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b4882621-1fe7-4855-9121-d8513d3ea8f9
📒 Files selected for processing (4)
packages/web/e2e/smoke.spec.tspackages/web/src/components/Navbar.tsxpackages/web/src/components/profile/PublicProfileOwnerControls.tsxpackages/web/src/components/tasks/CreateTaskDialog.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/web/src/components/Navbar.tsx
- packages/web/src/components/profile/PublicProfileOwnerControls.tsx
- packages/web/src/components/tasks/CreateTaskDialog.tsx
Before: one profileLink NavItem in routes.ts:509 was being asked to serve two semantically different jobs — link to /profile (edit form) AND link to /people/<handle> (public view). Navbar.tsx branched on publicProfileHref existence and swapped the destination silently. Net effect: once a user made their profile public, the "manage my profile" path disappeared from the navbar entirely. Mike caught it. Split into: - editProfileLink → /profile, "✏️ Edit Profile", "Edit bio, photo, privacy, and accounts" - publicProfileLink → dynamic href, "🌐 View Public Profile", "See your profile the way other humans see it" Navbar.tsx now renders BOTH links via getAuthenticatedProfileLinks() when the user has a public profile, just editProfileLink when they don't. ProfileCard.tsx:336 "View Profile" → "Preview public profile" (disambiguates the inside-edit-page link). Updated consumers in navSections, footerAppLinks, routeReviewNavItems, profile/page.tsx metadata. Removed unused profileLink import from site.ts. Bundled: restore 🔒 + 🌍 emojis to PrivacyToggle.tsx. The recent treaty-style migration kept the new <button aria-pressed disabled> accessibility wrapper and treaty-token colors (both wins) but threw out the toggle-state icons along with the brutalist styling. The emojis aren't decoration — they're concrete state cues for a binary privacy switch. aria-hidden so screen readers don't double-announce. qa-passed: skipped — UI label-only diff + pure helper function tested via Navbar.test.ts; pnpm --filter @optimitron/web exec tsc --noEmit clean.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 529-536: The current lookup uses comments.find(...) which returns
the first (oldest) matching comment; change both lookups that reference
packetMarker and legacyMarker (and the other block at the second occurrence) to
select the newest matching sticky comment instead—e.g., iterate comments in
reverse or use a findLast equivalent to locate the last comment whose body
includes packetMarker or legacyMarker so the code updates the most recent sticky
comment rather than a stale one.
In `@packages/web/src/lib/email/magic-link-render.ts`:
- Around line 22-23: The intro copy is specific to an HTML button but is reused
by buildMagicLinkText(), causing plain-text emails to incorrectly reference a
"button"; update the intro string (and any shared constant used by
buildMagicLinkText) to link-agnostic wording such as "Click the link to verify
your email and save your vote." so both HTML (where buttonLabel: "Save my vote"
remains) and plain-text variants are accurate; locate the intro constant
referenced by buildMagicLinkText and replace the phrase "Click the button below"
with a neutral alternative like "Click the link" or "Use the link."
In `@packages/web/src/lib/messaging.ts`:
- Line 283: Replace the hardcoded "1%" in the message string with the configured
treaty percentage by using the TREATY_REDUCTION_PCT value formatted with
fmtParam so the copy matches the model parameter; locate the message in
packages/web/src/lib/messaging.ts (the string that references POINT_NAME) and
change it to interpolate the formatted treaty percent (use the existing
TREATY_REDUCTION_PCT and fmtParam helpers) so the text reads like "Your
{treatyPct}% Treaty vote is saved…" while still including POINT_NAME.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7de20e04-3361-4cb6-a910-d6a49a225ee1
📒 Files selected for processing (22)
.github/scripts/generate-pr-preview-links.mjs.github/scripts/generate-pr-preview-links.test.mjs.github/workflows/ci.ymlpackages/web/e2e/email-screenshots.spec.tspackages/web/e2e/new-user-flow-screenshots.spec.tspackages/web/e2e/visual-regression.spec.tspackages/web/scripts/build-visual-review.mjspackages/web/src/app/profile/page.tsxpackages/web/src/components/Navbar.test.tspackages/web/src/components/Navbar.tsxpackages/web/src/components/dashboard/PrivacyToggle.tsxpackages/web/src/components/dashboard/ProfileCard.tsxpackages/web/src/components/landing/TreatyVoteFlow.tsxpackages/web/src/lib/__tests__/routes.test.tspackages/web/src/lib/email/__tests__/magic-link-email.test.tspackages/web/src/lib/email/__tests__/magic-link-send.test.tspackages/web/src/lib/email/magic-link-email.tspackages/web/src/lib/email/magic-link-render.tspackages/web/src/lib/email/magic-link.email.mdpackages/web/src/lib/messaging.tspackages/web/src/lib/routes.tspackages/web/src/lib/site.ts
💤 Files with no reviewable changes (1)
- packages/web/src/lib/site.ts
✅ Files skipped from review due to trivial changes (3)
- packages/web/src/components/dashboard/ProfileCard.tsx
- packages/web/e2e/new-user-flow-screenshots.spec.ts
- packages/web/src/app/profile/page.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/web/e2e/visual-regression.spec.ts
- packages/web/src/components/dashboard/PrivacyToggle.tsx
…kUserQuestion ceremony on every turn The hook auto-added Pending review items to .claude/state/review-queue-<branch>.md on every Write/Edit/MultiEdit touching shared files (messaging.ts touch added 47 routes; profile-link work added more) then blocked turn-end via Stop hook until I AskUserQuestion-ed through each item. Net effect: every multi-file change ended with stale "review this" prompts for work that had already shipped + been approved. Mike (verbatim): "do we need to disable some hooks or something that are fucking you up or getting you stuck? What is the deal here?" Removed: - PostToolUse Write/Edit/MultiEdit/AskUserQuestion review-loop-gate triggers - Stop hook review-loop-gate trigger Kept (auto-mode safety blocked editing): - SessionStart review-loop-gate trigger — benign without the per-edit feeders; fires once at startup, just reads the queue file. Safe to leave or remove manually. The /autoplan workflow + manual per-PR review + Vercel preview + CI tests already provide review coverage. The review-loop-gate duplicated work and added ceremony without catching anything the other paths missed.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.claude/plans/referred-voters-list.md:
- Line 17: Two unlabeled fenced code blocks containing ASCII diagrams should be
labeled as text to satisfy markdownlint MD040; locate the two triple-backtick
blocks that enclose the ASCII diagrams (the unlabeled ``` blocks) and change
their opening fences from ``` to ```text while leaving their closing fences as
``` so both diagram blocks are fenced with ```text.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5b2402cc-a85f-44f3-979a-aa4814340ed4
📒 Files selected for processing (15)
.claude/plans/referred-voters-list.md.claude/settings.json.github/scripts/audit-sentry-preview.mjs.github/scripts/audit-sentry-preview.test.mjs.github/workflows/smoke-deploy.ymlpackages/web/src/app/dashboard/page.tsxpackages/web/src/components/dashboard/HumanityManagerStatusPanel.test.tsxpackages/web/src/components/site/TreatyTaskDashboardClient.tsxpackages/web/src/lib/__tests__/dashboard.server.test.tspackages/web/src/lib/__tests__/humanity-manager-status.server.test.tspackages/web/src/lib/dashboard.server.tspackages/web/src/lib/humanity-manager-status-content.tsxpackages/web/src/lib/humanity-manager-status.server.tspackages/web/src/lib/profile-identity.server.tspackages/web/src/types/dashboard.ts
💤 Files with no reviewable changes (1)
- .claude/settings.json
✅ Files skipped from review due to trivial changes (1)
- packages/web/src/lib/tests/dashboard.server.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- .github/scripts/audit-sentry-preview.test.mjs
- .github/workflows/smoke-deploy.yml
- .github/scripts/audit-sentry-preview.mjs
- Added a check in the verify-ui-changes hook to flag commits that touch packages/web/src/ without staging TODO.md or including appropriate markers in the commit message. - This advisory-only check ensures that TODO.md is updated in the same commit as related changes, preventing silent drift. docs: Add thank-and-recruit dispatch plan for Humanity Management Status - Created a new markdown file detailing the plan to implement "thank" and "recruit" functionality for voters on the Humanity Management Status panel. - The plan includes audience targeting, research logs, proposed UI changes, and a step-by-step implementation guide. chore: Remove unused command from pre-commit hook - Deleted the command for review-loop-gate from the pre-commit hook to streamline the commit process. fix: Update voice-critic criteria to include strategic-job comparison - Added a new criterion to the voice-critic agent to ensure that new copy increases the target action compared to old copy. chore: Enable goals feature in Codex configuration - Updated the Codex configuration to enable the goals feature for enhanced functionality. chore: Update Husky pre-commit hook to include copy review gate - Added a command to run the copy review gate script in the pre-commit hook to ensure public copy is reviewed before committing. feat: Add new visual route for referendum one percent treaty - Introduced a new visual route for the "referendum-one-percent-treaty" in the visual routes configuration. feat: Include referendum one percent treaty in visual review build - Updated the build script for visual reviews to include the new "referendum-one-percent-treaty" route. feat: Create copy review gate script - Implemented a new script to enforce a review gate for public copy changes before allowing commits.
Preview deploy smoke failedTarget: https://optimitron-nvah3b4mr-mike-p-sinns-projects.vercel.app/
The smoke request uses the Vercel automation bypass header and checks HTTP 200, owned error markers, and expected h1 text. |
|
Code review — 3 security bugs, 3 CLAUDE.md violations. Issue 1 — Security: private profiles exposed + email enumeration oracle optimitron/packages/web/src/app/api/people/search/route.ts Lines 36 to 48 in 90a85c9 The Additionally, the Fix: add Issue 2 — Security: upsert silently un-deletes soft-deleted Persons optimitron/packages/web/src/app/api/tasks/route.ts Lines 121 to 124 in 90a85c9
The Fix: use Issue 3 — Security: optimitron/packages/web/src/app/api/tasks/route.ts Lines 182 to 197 in 90a85c9 When Fix: validate before accepting the ID: if (assigneePersonId) {
const person = await prisma.person.findFirst({
where: { id: assigneePersonId, isPublic: true, deletedAt: null },
select: { id: true },
});
if (!person) return NextResponse.json({ error: 'Person not found.' }, { status: 404 });
}Issue 4 — CLAUDE.md: tasks created with optimitron/packages/web/src/components/tasks/CreateTaskDialog.tsx Lines 350 to 380 in 90a85c9 The fetch body never includes Fix: import Issue 5 — CLAUDE.md: hardcoded optimitron/packages/web/src/components/dashboard/ReferralLinkEditor.tsx Lines 255 to 293 in 90a85c9 Three net-new or touched locations use banned hardcoded color literals. CLAUDE.md Visual Style Rules: "Never use: Hardcoded Line 257 (Save button): Replace with semantic tokens: Issue 6 — CLAUDE.md: hardcoded optimitron/packages/web/src/components/landing/TreatyVoteFlow.tsx Lines 972 to 976 in 90a85c9 This label was rewritten in this PR (old floating version deleted); the new version is subject to the ban on |
Summary
Review URLs
Preview deployment: https://optimitron-web-git-feature-public-9f8c82-mike-p-sinns-projects.vercel.app
Changed states to review:
Visual review: https://mikepsinn.github.io/optimitron/pr-85/76f177c47d32/latest.html
Validation
git diff --checkpnpm --filter @optimitron/web typecheck:fastpnpm --filter @optimitron/web test -- src/lib/__tests__/tasks.server.test.ts src/app/api/tasks/route.test.tspnpm --filter @optimitron/web copy:preview -- --routes=/profile,/peopleSummary by CodeRabbit
New Features
Improvements