Skip to content

Add EOS/EOP updates and magic-link spam guard#88

Merged
mikepsinn merged 30 commits into
mainfrom
feature/auth-magic-link-spam
Jun 19, 2026
Merged

Add EOS/EOP updates and magic-link spam guard#88
mikepsinn merged 30 commits into
mainfrom
feature/auth-magic-link-spam

Conversation

@mikepsinn

@mikepsinn mikepsinn commented May 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • reduce magic-link monitor noise and add sanitized magic-link logging/tests
  • add EOS/game surfaces and migrate vote-token naming toward EarthOptimizationPoint / point minting
  • fix EOP redemption so redeemed points are burned and cannot be transferred for a second redemption
  • make Playwright CI less likely to time out on a cold browser install

Local verification

  • pnpm --filter @optimitron/treasury-prize exec hardhat test test/EarthOptimizationPoint.test.ts test/VoterPrizeTreasury.test.ts
  • NODE_OPTIONS=--max-old-space-size=8192 pnpm --filter @optimitron/web run typecheck:fast
  • git diff --check (clean; CRLF warnings only)

Review links

Summary by CodeRabbit

  • New Features

    • Earth Optimization Services landing, interactive investment calculator, and Earth Optimization Game page.
  • Updates

    • System-wide switch from VOTE tokens to Earth Optimization Points across UI, balances, referrals, treasury redemption, previews, and contracts.
    • Navigation: new /eos and /game routes; home variant set to EOS landing.
  • Bug Fixes / Reliability

    • Improved magic-link rate limiting, structured logging, send-failure handling.
    • React magic-link emails no longer include monitor BCC.

Copilot AI review requested due to automatic review settings May 26, 2026 00:13
@vercel

vercel Bot commented May 26, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
optimitron-web Ready Ready Preview, Comment Jun 18, 2026 10:35pm

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Migrate VoteToken/VOTE flows to EarthOptimizationPoint/EOP across DB, contracts, server, cron, APIs, ABI, frontend pages/components and demos; add EOS/game landing pages; refactor magic-link spam-guard logging, email BCC behavior, and tests; update CI/playwright timeouts.

Changes

Point mint & EOS landing migration

Layer / File(s) Summary
DB migration, Prisma & Zod types
packages/db/prisma/migrations/20260607120000_rename_vote_token_mint_to_point_mint/migration.sql, packages/db/prisma/schema.prisma, packages/db/src/zod/index.ts
Renames DB enum/table to PointMint/PointMintStatus, updates Prisma schema relations (User.pointMints, Referendum.pointMints) and Zod exports/types to PointMint/PointMintStatus.
Contracts: EOP token and treasury changes
packages/treasury-prize/contracts/EarthOptimizationPoint.sol, packages/treasury-prize/contracts/VoterPrizeTreasury.sol, packages/treasury-shared/contracts/interfaces/IEarthOptimizationPoint.sol
Replaces VoteToken with EarthOptimizationPoint (EOP): contract names, events, revert strings, treasury snapshot/redemption logic, events, and public view functions updated to point-centric names/types (adds burnForRedemption).
Deploy script, ABI & addresses
packages/treasury-prize/scripts/deploy-voter-prize-treasury.ts, packages/treasury-prize/src/abi.ts, packages/treasury-shared/src/addresses.ts, packages/treasury-prize/package.json
Deploy flow updated to deploy and wire EarthOptimizationPoint; ABIs and shared addresses replace voteToken entries with earthOptimizationPoint; package description updated.
Server helpers & cron
packages/web/src/lib/contracts/server-client.ts, packages/web/src/app/api/cron/point-mint/route.ts, packages/web/src/app/api/cron/point-mint/route.test.ts
Replace getVoteTokenContract/minter env with getEarthOptimizationPointContract/EOP env; cron route processes prisma.pointMint rows, uses EOP_CHAIN_ID, calls batchMintForVoters on EOP contract; tests updated.
Referral point-mint sync & tests
packages/web/src/lib/referral-point-mint.server.ts, packages/web/src/lib/__tests__/referral-point-mint.server.test.ts
Renamed/rewired sync functions to point-mint variants; persistence now targets prisma.pointMint with same rewrite semantics; tests updated to pointMint* mocks and assertions.
API routes & tests (points)
packages/web/src/app/api/points/balance/route.ts, packages/web/src/app/api/prize-treasury/status/route.ts, packages/web/src/app/api/referendums/[slug]/vote/route.ts, packages/web/src/app/api/personhood/world-id/verify/route.ts, plus related test files
Handlers and tests updated to use point-mint model/fields and EOP_CHAIN_ID; response shapes renamed (totalPoints, confirmedPointMints, pointTotalSupplySnapshot, referrerPointMint, referralPointMintsQueued).
Frontend: pages, components, routes & messaging
packages/web/src/lib/routes.ts, packages/web/src/lib/site.ts, packages/web/src/app/eos/*, packages/web/src/app/game/*, packages/web/src/app/page.tsx, packages/web/src/components/*
Added EOS landing and game pages; route catalog and site metadata updated; many components swapped from VOTE → POINT naming and formatters (Prize UI, balance card, treasury deposit, demo slides, game score, landing components).
Demo & parameters
packages/web/src/lib/demo/parameters.ts, packages/web/src/lib/demo-script.ts, slide files
Demo parameter source and slide IDs updated to use EARTH_OPTIMIZATION_POINT_VALUE and point-based slide registry; script segments swapped accordingly.
Data parameters additions
packages/data/src/parameters/parameters-calculations-citations.ts
Adds many new defense/earth/mechanism parameters, definition inputs, citations, and updates wiring and PARAMETER_STATS counts; removes vote value parameters.
Magic-link spam guard, email result & tests
packages/web/src/lib/auth-spam-guard.server.ts, packages/web/src/lib/email/magic-link-email.ts, packages/web/src/lib/email/resend.ts, packages/web/src/lib/__tests__/auth-spam-guard.server.test.ts, packages/web/src/lib/__tests__/resend.test.ts
Extracts request headers into MagicLinkRequestContext, implements countRecentMagicLinkTokens, changes suppression to depend on recent-token count, returns send metadata (existingUser, providerMessageId), excludes monitor BCC for scope === "magic_link", adds structured JSON logging and tests asserting logged outcomes and BCC behavior.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant NextAPI
  participant PrismaDB
  participant EOPContract
  Client->>NextAPI: POST /api/cron/point-mint (cron)
  NextAPI->>PrismaDB: find pending pointMint rows
  NextAPI->>EOPContract: batchMintForVoters(tx)
  EOPContract-->>NextAPI: txHash / success
  NextAPI->>PrismaDB: update rows -> CONFIRMED with txHash
Loading

Estimated code review effort: 🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs:

"A rabbit hopped through the logs so bright,
Counting tokens left and right,
Magic links no longer hide—
Context flows with careful pride!"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/auth-magic-link-spam

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR reduces noise in the email monitor by removing automatic monitor BCC on magic-link emails, and adds structured (sanitized) logging for /api/auth/signin/email to better understand where signup spam is coming from—while preserving the existing repeated-address suppression behavior with test coverage.

Changes:

  • Make monitor-BCC behavior scope-aware so "magic_link" emails don’t add EMAIL_MONITOR_BCC.
  • Add structured logging around magic-link send/suppress/fail outcomes (with request context like referer host/path, callback host, etc.).
  • Extend tests to cover both “sent” and “suppressed” outcomes and the new magic-link BCC behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/web/src/lib/email/resend.ts Skip monitor BCC for scope: "magic_link"; minor refactor of email body composition call.
packages/web/src/lib/email/magic-link-email.ts Return { existingUser, providerMessageId } metadata for downstream logging.
packages/web/src/lib/auth-spam-guard.server.ts Add sanitized structured logging and refactor token counting used by magic-link suppression.
packages/web/src/lib/tests/resend.test.ts Add regression test ensuring magic-link React emails do not include monitor BCC.
packages/web/src/lib/tests/auth-spam-guard.server.test.ts Assert structured logs for “suppressed” and “sent” magic-link outcomes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/web/src/lib/auth-spam-guard.server.ts
Comment thread packages/web/src/lib/auth-spam-guard.server.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f58022d6af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/web/src/lib/auth-spam-guard.server.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/lib/__tests__/auth-spam-guard.server.test.ts`:
- Around line 64-68: The helper lastAuthLog() currently assumes the final
console.log is the auth JSON and parses mock.calls.at(-1), which is flaky;
change lastAuthLog to scan consoleLogSpy.mock.calls backward, attempt JSON.parse
on each call[0], and return the first parsed object whose msg ===
"auth_magic_link_request"; if none found, throw or fail with a clear message.
Use the existing consoleLogSpy.mock.calls and JSON.parse, and reference the
lastAuthLog() function so the test locates and returns the correct auth log even
if unrelated logs were printed.

In `@packages/web/src/lib/auth-spam-guard.server.ts`:
- Around line 101-108: The auth log is currently writing uncontrolled
provider/runtime messages (error.message) into the sanitized auth log in
logMagicLinkRequest; change this to emit a stable, allowlisted failure reason
code (e.g., "provider_error", "rate_limited", "invalid_recipient", "unknown")
mapped from the thrown error or outcome, and send the raw error details only to
the separate error channel (e.g., processLogger.error or an error monitoring
call). Update logMagicLinkRequest and the nearby handling that writes
outcome/reason (the block handling outcome="failed") to perform the
mapping/whitelist and include recentTokenCount/providerMessageId as before, and
ensure raw exception is logged only to the error logger so the sanitized auth
log cannot contain uncontrolled messages.
🪄 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: 11f48190-7910-462e-8dfd-5fed4c70f9ac

📥 Commits

Reviewing files that changed from the base of the PR and between 919760d and f58022d.

📒 Files selected for processing (5)
  • packages/web/src/lib/__tests__/auth-spam-guard.server.test.ts
  • packages/web/src/lib/__tests__/resend.test.ts
  • packages/web/src/lib/auth-spam-guard.server.ts
  • packages/web/src/lib/email/magic-link-email.ts
  • packages/web/src/lib/email/resend.ts

Comment thread packages/web/src/lib/__tests__/auth-spam-guard.server.test.ts
Comment thread packages/web/src/lib/auth-spam-guard.server.ts
@claude

claude Bot commented May 26, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

PR review packet

Start here

  • 🖼️ Visual review
  • 🚀 Preview deployment
  • ☝️ Cmd/Ctrl-click review links to keep this PR open.
  • 🔑 ?login=demo signs in as the demo user; ?logout=1 clears the session.
  • 💬 For a visual problem, use the comment button in latest.html or reply here with @claude and the checklist item.

Review checklist

Changed files considered
  • .claude/agents/voice-critic.md
  • .claude/plans/eos-landing.md
  • .github/scripts/resolve-preview-neon-env.mjs
  • .github/workflows/ci.yml
  • .github/workflows/smoke-deploy.yml
  • CLAUDE.md
  • TODO.md
  • docs/MCP_SERVER.md
  • docs/PREVIEW_DATA_PRIVACY.md
  • docs/SCHEMA_USAGE_AUDIT.md
  • docs/generated/schema-usage-audit.json
  • packages/data/src/datasets/wishonia-agencies.ts
  • packages/data/src/parameters/parameters-calculations-citations.ts
  • packages/data/src/referendums/court-of-humanity.ts
  • packages/db/prisma/anonymization-updates.sql
  • packages/db/prisma/migrations/20260607120000_rename_vote_token_mint_to_point_mint/migration.sql
  • packages/db/prisma/migrations/20260614120000_add_task_applications/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/db/src/__tests__/zod-validators.test.ts
  • packages/db/src/managed-data/managed-seed-data.ts
  • packages/db/src/managed-data/optimize-earth-task-tree.test.ts
  • packages/db/src/managed-data/optimize-earth-task-tree.ts
  • packages/db/src/managed-data/sync-managed-tasks.test.ts
  • packages/db/src/managed-data/sync-managed-tasks.ts
  • packages/db/src/schema-usage-audit.ts
  • packages/db/src/task-keys.ts
  • packages/db/src/zod/index.ts
  • packages/treasury-prize/contracts/EarthOptimizationPoint.sol
  • packages/treasury-prize/contracts/VoterPrizeTreasury.sol
  • packages/treasury-prize/package.json
  • packages/treasury-prize/scripts/deploy-voter-prize-treasury.ts
  • packages/treasury-prize/src/abi.ts
  • packages/treasury-prize/test/EarthOptimizationPoint.test.ts
  • packages/treasury-prize/test/VoterPrizeTreasury.test.ts
  • packages/treasury-shared/contracts/interfaces/IEarthOptimizationPoint.sol
  • packages/treasury-shared/src/addresses.ts
  • packages/web/AGENTS.md
  • packages/web/e2e/contrast-audit.spec.ts
  • packages/web/e2e/landing-funnel.spec.ts
  • packages/web/e2e/voter-prize.spec.ts
  • ...and 191 more

Updated automatically when this PR's preview or visual review reruns.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/db/prisma/schema.prisma (1)

4874-4918: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

PointMint still cannot identify the vote it claims to represent.

Line 4874 says this row links a referendum vote to a mint, but the schema only stores the referrer, referendum, and nullifierHash. Without a direct ReferendumVote FK (or another stable vote-level identifier), the database cannot enforce that a mint was issued for the correct vote or make that provenance queryable later.

🤖 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/db/prisma/schema.prisma` around lines 4874 - 4918, PointMint
currently lacks a direct FK to the vote it represents; add a voteId field on the
PointMint model that references the ReferendumVote primary key and wire up the
relation (e.g., fields: [voteId], references: [id], onDelete: Cascade) so
provenance and referential integrity are enforced; update the model-level
constraints (replace or extend @@unique([nullifierHash, referendumId]) to
include voteId or add a separate unique constraint as appropriate) and add the
inverse relation on ReferendumVote if present so queries can traverse from a
vote to its PointMint(s).
packages/web/src/app/api/cron/point-mint/route.ts (1)

40-60: ⚠️ Potential issue | 🟠 Major

Add recovery for orphaned pointMint rows stuck in SUBMITTED
packages/web/src/app/api/cron/point-mint/route.ts marks pointMint records SUBMITTED before the on-chain call, but the cron only queries PENDING on subsequent runs and no other code path updates SUBMITTED back to PENDING/FAILED for retry (referral sync rewrites only PENDING/FAILED). Add a periodic cleanup/retry that reverts SUBMITTED rows older than a threshold (e.g., via submittedAt) back to a retryable state.

🤖 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/src/app/api/cron/point-mint/route.ts` around lines 40 - 60, Add
a recovery step in the cron handler in route.ts that flips orphaned pointMint
rows from SUBMITTED back to a retryable status (e.g., PENDING) when their
submittedAt timestamp is older than a configurable threshold; implement this by
calling prisma.pointMint.updateMany before you fetch pendingMints (use the same
BATCH_SIZE/ids context if needed) and target records where status ===
"SUBMITTED" && submittedAt < Date.now() - THRESHOLD_MS, updating status to
"PENDING" (and optionally incrementing a retry counter or setting lastTriedAt)
so those mints will be reprocessed by the existing logic that reads
pendingMints.
packages/treasury-prize/test/VoterPrizeTreasury.test.ts (1)

290-410: ⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Missing critical test: post-redemption transfer scenario.

The test suite validates that:

  • Same address cannot redeem twice (line 342-356) ✓
  • Pre-snapshot transfers work correctly (line 659-696) ✓

But does NOT test the critical vulnerability: redeem → transfer → redeem by different address.The search results discuss ERC-4626 vault standards and token security, but don't directly address the specific double-redemption-via-transfer vulnerability. The standard practice is that shares are "burned to redeem the corresponding underlying assets", which this implementation does not do.

🧪 Suggested test to add after line 356
it("SECURITY: prevents redemption of transferred EOP post-redemption", async function () {
  const { treasury, usdc, aavePool, pointToken, contributor1, voter1, voter2 } =
    await loadFixture(deployFixture);

  // Setup: fund treasury
  await treasury.connect(contributor1).deposit(parseUSDC(30_000));
  await aavePool.simulateYield(
    await treasury.getAddress(),
    parseUSDC(6_000)
  );
  
  // Snapshot: voter1=1 EOP, voter2=1 EOP, voter3=1 EOP, total=3 EOP
  await treasury.updateMetrics(HEALTH_THRESHOLD, INCOME_THRESHOLD);
  await treasury.snapshotPointSupply();
  await time.increase(Number(FIFTEEN_YEARS));

  // voter1 redeems their 1 EOP share (1/3 of 36,000 = 12,000 USDC)
  const bal1Before = await usdc.balanceOf(voter1.address);
  await treasury.connect(voter1).redeemEarthOptimizationPoints();
  const bal1After = await usdc.balanceOf(voter1.address);
  expect(bal1After - bal1Before).to.be.closeTo(
    parseUSDC(12_000),
    parseUSDC(1)
  );

  // voter1 still holds 1 EOP (not burned on redemption)
  expect(await pointToken.balanceOf(voter1.address)).to.equal(ONE_POINT);

  // voter1 transfers their EOP to voter2
  await pointToken
    .connect(voter1)
    .transfer(voter2.address, ONE_POINT);

  // voter2 now has 2 EOP (original 1 + transferred 1)
  expect(await pointToken.balanceOf(voter2.address)).to.equal(
    ONE_POINT * 2n
  );

  // VULNERABILITY: voter2 can redeem 2 EOP (2/3 of pool = 24,000 USDC)
  // This drains 36,000 total from a pool that should only give 36,000 to all 3 voters
  // Expected behavior: This should either:
  // A) Revert because voter1's EOP was already redeemed, OR
  // B) Treasury should have burned voter1's EOP on redemption to prevent this
  const bal2Before = await usdc.balanceOf(voter2.address);
  await treasury.connect(voter2).redeemEarthOptimizationPoints();
  const bal2After = await usdc.balanceOf(voter2.address);
  
  // Currently this succeeds and drains 24,000 USDC
  expect(bal2After - bal2Before).to.be.closeTo(
    parseUSDC(24_000),
    parseUSDC(1)
  );

  // Total redeemed: 12,000 (voter1) + 24,000 (voter2) = 36,000
  // voter3 will fail to redeem because pool is empty
  await expect(
    treasury.connect(voter3).redeemEarthOptimizationPoints()
  ).to.be.reverted; // Aave withdraw reverts when insufficient funds
});
🤖 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/treasury-prize/test/VoterPrizeTreasury.test.ts` around lines 290 -
410, The test suite is missing a security test for the "redeem → transfer →
redeem by different address" vulnerability; add a test that after calling
redeemEarthOptimizationPoints by an address you assert the caller's EOP balance
is reduced or the token burned/marked redeemed (inspect pointToken.balanceOf and
treasury redemption state), then attempt to transfer those EOP to another
address and assert that a subsequent redeemEarthOptimizationPoints by the
recipient is reverted; if the contract currently allows this flow, fix the
contract so redeemEarthOptimizationPoints either burns the caller's EOP via
pointToken (or calls a burnOnRedeem(address) function) or marks those token
IDs/amounts redeemed in the treasury (update the redemption tracking used in
redeemEarthOptimizationPoints) to prevent double-redemption.
packages/treasury-prize/src/abi.ts (1)

1-383: ⚠️ Potential issue | 🟠 Major

Fix ABI completeness: exported ABI fragments don’t match compiled contracts
packages/treasury-prize/src/abi.ts omits several function/event entries that exist in the compiled artifacts. Examples: EarthOptimizationPoint is missing batchMintForVoters, mintForVoter, claimed, owner, setPrizeTreasury, transferFrom, admin ownership-transfer events; VoterPrizeTreasury is missing ERC20 function fragments like transfer, transferFrom, allowance, approve, plus contract functions like aToken, aavePool, updateMetrics, snapshotPointSupply, owner, etc. Add the missing fragments (or clearly document and enforce that this ABI is an intentional minimal subset that covers all current call sites).

🤖 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/treasury-prize/src/abi.ts` around lines 1 - 383, The exported ABI
arrays are incomplete vs the compiled contracts; update
earthOptimizationPointAbi and voterPrizeTreasuryAbi to include the missing
function and event fragments shown in the review (e.g., EarthOptimizationPoint:
batchMintForVoters, mintForVoter, claimed, owner, setPrizeTreasury,
transferFrom, OwnershipTransferred event and other ownership/admin events;
VoterPrizeTreasury: transfer, transferFrom, allowance, approve, aToken,
aavePool, updateMetrics, snapshotPointSupply, owner, and any corresponding
events like PointSupplySnapshotted/OwnershipTransferred). Locate the two exports
(earthOptimizationPointAbi and voterPrizeTreasuryAbi) and either append the full
missing function/event descriptors matching the compiled artifact shapes or
replace the arrays with the canonical ABI from the build output; alternatively
add a clear comment and runtime assertion that the file is intentionally a
minimal subset and enforce that all call sites only rely on included fragments.
Ensure each added fragment uses the correct name, type, inputs/outputs and
stateMutability to match the compiled JSON so consumers won’t fail at runtime.
🧹 Nitpick comments (2)
packages/db/src/zod/index.ts (1)

1913-1914: 💤 Low value

Update the section comment to reflect the new naming.

The section comment still references "VOTE TOKEN" but the model has been renamed to PointMint. Update the comment to match the current terminology.

📝 Suggested update
 // ============================================================================
-// VOTE TOKEN & VOTER PRIZE TREASURY
+// POINT MINT & VOTER PRIZE TREASURY
 // ============================================================================
🤖 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/db/src/zod/index.ts` around lines 1913 - 1914, The section comment
currently reads "VOTE TOKEN & VOTER PRIZE TREASURY" but the model was renamed to
PointMint; update that comment to use the new terminology (e.g., "POINT MINT &
VOTER PRIZE TREASURY" or similar) so it matches the PointMint model; locate the
comment near the PointMint-related zod schemas or the PointMint type
declarations in this file and replace the old "VOTE TOKEN" wording with "POINT
MINT" throughout.
packages/web/src/components/demo/slides/sierra/slide-three-scenarios-all-win.tsx (1)

12-12: ⚡ Quick win

Rename voteValue to pointValue for consistency.

The variable is sourcing from EARTH_OPTIMIZATION_POINT_VALUE but retains the old voteValue name. Renaming it to pointValue maintains consistency with the migration in other files (e.g., slide-dominant-assurance-contract.tsx line 17, slide-point-value-asymmetry.tsx line 16) and prevents confusion.

♻️ Proposed rename
-const voteValue = formatCurrency(EARTH_OPTIMIZATION_POINT_VALUE.value);
+const pointValue = formatCurrency(EARTH_OPTIMIZATION_POINT_VALUE.value);
 const lifetimeGain = formatCurrency(TREATY_TRAJECTORY_LIFETIME_INCOME_GAIN_PER_CAPITA.value);

Then update the usage on line 36:

-            {voteValue}+
+            {pointValue}+
🤖 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/src/components/demo/slides/sierra/slide-three-scenarios-all-win.tsx`
at line 12, Rename the local variable voteValue to pointValue so it reflects its
source EARTH_OPTIMIZATION_POINT_VALUE; change the declaration where
formatCurrency(EARTH_OPTIMIZATION_POINT_VALUE.value) is assigned to use the
identifier pointValue and update all subsequent uses of voteValue (e.g., the
usage around the slide rendering at the later JSX) to pointValue; keep the call
to formatCurrency and the EARTH_OPTIMIZATION_POINT_VALUE reference unchanged.
🤖 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/data/src/parameters/parameters-calculations-citations.ts`:
- Around line 11207-11219: Update the MECHANISM_SHIRT_CASCADE_P_SUCCESS
Parameter to use the same dimensionless unit as the other probability
parameters: change its unit from "rate" to "ratio" in the
MECHANISM_SHIRT_CASCADE_P_SUCCESS object so it matches other mechanism
probability parameters (e.g., the ones near MECHANISM_*_P_* entries) and
reflects that probabilities are dimensionless ratios.
- Around line 6650-6663: The MECHANISM_LOVING_TAKEOVER_CAPITAL parameter
duplicates DEFENSE_TAKEOVER_COST_TOTAL; remove the duplicate definition and
either delete MECHANISM_LOVING_TAKEOVER_CAPITAL and update callers to use
DEFENSE_TAKEOVER_COST_TOTAL, or keep the symbol but change
MECHANISM_LOVING_TAKEOVER_CAPITAL to a reference form by setting its formula to
"DEFENSE_TAKEOVER_COST_TOTAL" (and drop the duplicated value/description) so all
logic points use the single canonical DEFENSE_TAKEOVER_COST_TOTAL parameter.

In
`@packages/db/prisma/migrations/20260607120000_rename_vote_token_mint_to_point_mint/migration.sql`:
- Around line 1-13: Add a rollback (down) migration that reverses the renames in
20260607120000_rename_vote_token_mint_to_point_mint/migration.sql by renaming
PointMint back to VoteTokenMint and PointMintStatus back to VoteTokenMintStatus
and reverting the constraint and index names (reverse each RENAME TO in the
file), or explicitly confirm the project intends up-only Prisma migrations and
document that decision; also update packages/db/prisma/anonymization-updates.sql
to replace references to public."VoteTokenMint" with public."PointMint" (or add
a safe existence check/guard around queries that reference
public."VoteTokenMint") so runtime SQL won’t fail after the rename.

In `@packages/treasury-prize/contracts/VoterPrizeTreasury.sol`:
- Around line 167-187: The redemption currently marks redemption per address
(hasRedeemedPoints) but does not burn or lock EOP tokens, allowing the same
token to be transferred and redeemed multiple times; modify
redeemEarthOptimizationPoints (or the EOP interaction around it) to require and
consume the tokens on redemption — e.g., call the EOP token's burnFrom or
transferFrom to move/burn the caller's pointBalance before or immediately after
computing assets and before setting hasRedeemedPoints, or require prior
approve+burnFrom so the contract actually reduces total supply/locks the tokens
when pointSupplySnapshotted is true; ensure you reference
earthOptimizationPoint, redeemEarthOptimizationPoints, hasRedeemedPoints,
pointSupplySnapshotted and pointTotalSupplySnapshot so the change prevents
double-redemption while preserving snapshot logic.

In `@packages/web/src/app/game/page.tsx`:
- Around line 14-15: The current expression building lateEmployeeTasks uses
treatyParentTask?.task.childTasks which will throw if treatyParentTask exists
but its task is nullish; change the access to guard task as well (use optional
chaining on task: treatyParentTask?.task?.childTasks ?? []) so null/undefined
task doesn't cause a TypeError, keeping the cast to TaskCardTask[] as needed and
updating the symbol lateEmployeeTasks accordingly.
- Around line 12-15: The unsafe double-casts on lateEmployeeProgramTask and
lateEmployeeTasks come from decorateTask/getTaskDetailData typing childTasks as
unknown[]; fix decorateTask so its decoratedChildTasks is typed as
TaskCardTask[] | undefined (and update decorateTask's return type accordingly)
so getTaskDetailData propagates childTasks with the proper TaskCardTask[] type;
once decorateTask/getTaskDetailData signatures are updated, remove the as
unknown/as TaskCardTask[] and the cast on lateEmployeeProgramTask in page.tsx
and let the correct types flow to lateEmployeeProgramTask and lateEmployeeTasks.

In `@packages/web/src/components/prize/VoterPrizeTreasuryDeposit.tsx`:
- Line 21: Replace the obvious test value in the PRESET_AMOUNTS constant inside
the VoterPrizeTreasuryDeposit component: remove or replace "9999999999999999"
with a sensible production cap (e.g., "10000" or "100000") or simply omit it
from PRESET_AMOUNTS so the preset list only contains realistic deposit options;
update any UI/validation expectations that assume the prior extreme value.

In `@packages/web/src/lib/impact-receipts.server.ts`:
- Line 94: The environment variable list used to determine the chain id omits
the legacy VOTE_TOKEN_CHAIN_ID, so current deployments without rotated envs will
default to "84532" and scan the wrong network; update the chain-id fallback
expression that assigns raw to include process.env.VOTE_TOKEN_CHAIN_ID (e.g.,
process.env.VOTE_TOKEN_CHAIN_ID ?? process.env.TREASURY_CHAIN_ID ??
process.env.EOP_CHAIN_ID ?? "84532") so VOTE_TOKEN_CHAIN_ID is honored during
migration, keeping the rest of the fallback order and variable name (raw)
intact.

In `@packages/web/src/lib/routes.ts`:
- Around line 976-988: Remove the TODO(copy) placeholders from the route
metadata for the "The Earth Optimization Game" route: finalize or replace the
provisional strings for label, description, tagline, cta (and any associated
fields like copyPreview, reviewName, screenshot) or delete the TODO comments
altogether so no TODO-gated copy ships; locate the route object containing
label: "The Earth Optimization Game" and update the description/tagline/cta to
final copy (or remove the TODO markers and set copyPreview/reviewName
appropriately) before merging.

In `@packages/web/src/lib/site.ts`:
- Around line 596-617: The production metadata in site.ts contains leftover
TODO(copy) markers and placeholder text for keys title, description,
openGraphTitle, openGraphDescription, openGraphImage.alt, twitterTitle, and
twitterDescription; update these keys with finalized copy (or remove the TODO
comments and replace the placeholder lines with the approved/production strings)
so no TODOs remain in root metadata before merging, ensuring openGraphImage
still includes valid url/width/height and alt text is updated accordingly.

---

Outside diff comments:
In `@packages/db/prisma/schema.prisma`:
- Around line 4874-4918: PointMint currently lacks a direct FK to the vote it
represents; add a voteId field on the PointMint model that references the
ReferendumVote primary key and wire up the relation (e.g., fields: [voteId],
references: [id], onDelete: Cascade) so provenance and referential integrity are
enforced; update the model-level constraints (replace or extend
@@unique([nullifierHash, referendumId]) to include voteId or add a separate
unique constraint as appropriate) and add the inverse relation on ReferendumVote
if present so queries can traverse from a vote to its PointMint(s).

In `@packages/treasury-prize/src/abi.ts`:
- Around line 1-383: The exported ABI arrays are incomplete vs the compiled
contracts; update earthOptimizationPointAbi and voterPrizeTreasuryAbi to include
the missing function and event fragments shown in the review (e.g.,
EarthOptimizationPoint: batchMintForVoters, mintForVoter, claimed, owner,
setPrizeTreasury, transferFrom, OwnershipTransferred event and other
ownership/admin events; VoterPrizeTreasury: transfer, transferFrom, allowance,
approve, aToken, aavePool, updateMetrics, snapshotPointSupply, owner, and any
corresponding events like PointSupplySnapshotted/OwnershipTransferred). Locate
the two exports (earthOptimizationPointAbi and voterPrizeTreasuryAbi) and either
append the full missing function/event descriptors matching the compiled
artifact shapes or replace the arrays with the canonical ABI from the build
output; alternatively add a clear comment and runtime assertion that the file is
intentionally a minimal subset and enforce that all call sites only rely on
included fragments. Ensure each added fragment uses the correct name, type,
inputs/outputs and stateMutability to match the compiled JSON so consumers won’t
fail at runtime.

In `@packages/treasury-prize/test/VoterPrizeTreasury.test.ts`:
- Around line 290-410: The test suite is missing a security test for the "redeem
→ transfer → redeem by different address" vulnerability; add a test that after
calling redeemEarthOptimizationPoints by an address you assert the caller's EOP
balance is reduced or the token burned/marked redeemed (inspect
pointToken.balanceOf and treasury redemption state), then attempt to transfer
those EOP to another address and assert that a subsequent
redeemEarthOptimizationPoints by the recipient is reverted; if the contract
currently allows this flow, fix the contract so redeemEarthOptimizationPoints
either burns the caller's EOP via pointToken (or calls a burnOnRedeem(address)
function) or marks those token IDs/amounts redeemed in the treasury (update the
redemption tracking used in redeemEarthOptimizationPoints) to prevent
double-redemption.

In `@packages/web/src/app/api/cron/point-mint/route.ts`:
- Around line 40-60: Add a recovery step in the cron handler in route.ts that
flips orphaned pointMint rows from SUBMITTED back to a retryable status (e.g.,
PENDING) when their submittedAt timestamp is older than a configurable
threshold; implement this by calling prisma.pointMint.updateMany before you
fetch pendingMints (use the same BATCH_SIZE/ids context if needed) and target
records where status === "SUBMITTED" && submittedAt < Date.now() - THRESHOLD_MS,
updating status to "PENDING" (and optionally incrementing a retry counter or
setting lastTriedAt) so those mints will be reprocessed by the existing logic
that reads pendingMints.

---

Nitpick comments:
In `@packages/db/src/zod/index.ts`:
- Around line 1913-1914: The section comment currently reads "VOTE TOKEN & VOTER
PRIZE TREASURY" but the model was renamed to PointMint; update that comment to
use the new terminology (e.g., "POINT MINT & VOTER PRIZE TREASURY" or similar)
so it matches the PointMint model; locate the comment near the PointMint-related
zod schemas or the PointMint type declarations in this file and replace the old
"VOTE TOKEN" wording with "POINT MINT" throughout.

In
`@packages/web/src/components/demo/slides/sierra/slide-three-scenarios-all-win.tsx`:
- Line 12: Rename the local variable voteValue to pointValue so it reflects its
source EARTH_OPTIMIZATION_POINT_VALUE; change the declaration where
formatCurrency(EARTH_OPTIMIZATION_POINT_VALUE.value) is assigned to use the
identifier pointValue and update all subsequent uses of voteValue (e.g., the
usage around the slide rendering at the later JSX) to pointValue; keep the call
to formatCurrency and the EARTH_OPTIMIZATION_POINT_VALUE reference unchanged.
🪄 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: 17a1661f-fd3e-4b86-a788-224fe1ca5cdc

📥 Commits

Reviewing files that changed from the base of the PR and between f58022d and c25b4e1.

📒 Files selected for processing (69)
  • TODO.md
  • packages/data/src/parameters/parameters-calculations-citations.ts
  • packages/db/prisma/migrations/20260607120000_rename_vote_token_mint_to_point_mint/migration.sql
  • packages/db/prisma/schema.prisma
  • packages/db/src/zod/index.ts
  • packages/treasury-prize/contracts/EarthOptimizationPoint.sol
  • packages/treasury-prize/contracts/VoterPrizeTreasury.sol
  • packages/treasury-prize/package.json
  • packages/treasury-prize/scripts/deploy-voter-prize-treasury.ts
  • packages/treasury-prize/src/abi.ts
  • packages/treasury-prize/test/EarthOptimizationPoint.test.ts
  • packages/treasury-prize/test/VoteToken.test.ts
  • packages/treasury-prize/test/VoterPrizeTreasury.test.ts
  • packages/treasury-shared/contracts/interfaces/IEarthOptimizationPoint.sol
  • packages/treasury-shared/src/addresses.ts
  • packages/web/src/app/api/cron/point-mint/route.test.ts
  • packages/web/src/app/api/cron/point-mint/route.ts
  • packages/web/src/app/api/game-stats/route.ts
  • packages/web/src/app/api/personhood/world-id/verify/route.test.ts
  • packages/web/src/app/api/personhood/world-id/verify/route.ts
  • packages/web/src/app/api/points/balance/route.test.ts
  • packages/web/src/app/api/points/balance/route.ts
  • packages/web/src/app/api/prize-treasury/status/route.test.ts
  • packages/web/src/app/api/prize-treasury/status/route.ts
  • packages/web/src/app/api/referendums/[slug]/vote/route.test.ts
  • packages/web/src/app/api/referendums/[slug]/vote/route.ts
  • packages/web/src/app/contribute/page.tsx
  • packages/web/src/app/eos/page.logged-out.md
  • packages/web/src/app/eos/page.tsx
  • packages/web/src/app/game/page.logged-out.md
  • packages/web/src/app/game/page.tsx
  • packages/web/src/app/love/page.logged-out.md
  • packages/web/src/app/page.tsx
  • packages/web/src/app/prize/page.tsx
  • packages/web/src/app/store/page.logged-out.md
  • packages/web/src/components/demo/slides/index.ts
  • packages/web/src/components/demo/slides/sierra/slide-dominant-assurance-contract.tsx
  • packages/web/src/components/demo/slides/sierra/slide-point-dollar-value.tsx
  • packages/web/src/components/demo/slides/sierra/slide-point-value-asymmetry.tsx
  • packages/web/src/components/demo/slides/sierra/slide-prize-pool-vs-index-fund.tsx
  • packages/web/src/components/demo/slides/sierra/slide-three-scenarios-all-win.tsx
  • packages/web/src/components/game/GameScoreBar.tsx
  • packages/web/src/components/landing/DecisionMatrixSection.tsx
  • packages/web/src/components/prize/EarthOptimizationPointsBalanceCard.tsx
  • packages/web/src/components/prize/PrizeCalculator.tsx
  • packages/web/src/components/prize/VoterPrizeTreasuryDeposit.tsx
  • packages/web/src/components/profile/ProfileHub.tsx
  • packages/web/src/components/site/EarthOptimizationGameLandingPage.tsx
  • packages/web/src/components/site/EarthOptimizationServicesLandingPage.tsx
  • packages/web/src/components/site/EosInvestmentCalculator.tsx
  • packages/web/src/lib/__tests__/auth-spam-guard.server.test.ts
  • packages/web/src/lib/__tests__/impact-receipts.server.test.ts
  • packages/web/src/lib/__tests__/referral-point-mint.server.test.ts
  • packages/web/src/lib/__tests__/routes.test.ts
  • packages/web/src/lib/__tests__/site.test.ts
  • packages/web/src/lib/auth-spam-guard.server.ts
  • packages/web/src/lib/contracts/server-client.ts
  • packages/web/src/lib/daily-activity-digest.server.ts
  • packages/web/src/lib/dashboard.server.ts
  • packages/web/src/lib/demo-script.ts
  • packages/web/src/lib/demo/parameters.ts
  • packages/web/src/lib/env.ts
  • packages/web/src/lib/impact-receipts.server.ts
  • packages/web/src/lib/messaging.ts
  • packages/web/src/lib/prize-deposit-hypercert.server.ts
  • packages/web/src/lib/referral-point-mint.server.ts
  • packages/web/src/lib/routes.ts
  • packages/web/src/lib/site.ts
  • packages/web/vercel.json
💤 Files with no reviewable changes (1)
  • packages/treasury-prize/test/VoteToken.test.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/treasury-prize/package.json
  • packages/web/src/app/store/page.logged-out.md
  • packages/web/src/app/eos/page.tsx
  • packages/web/src/app/love/page.logged-out.md
  • TODO.md
  • packages/web/src/app/prize/page.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/web/src/lib/auth-spam-guard.server.ts

Comment thread packages/data/src/parameters/parameters-calculations-citations.ts Outdated
Comment thread packages/data/src/parameters/parameters-calculations-citations.ts Outdated
Comment thread packages/treasury-prize/contracts/VoterPrizeTreasury.sol
Comment thread packages/web/src/app/game/page.tsx
Comment thread packages/web/src/app/game/page.tsx Outdated
Comment thread packages/web/src/components/prize/VoterPrizeTreasuryDeposit.tsx
Comment thread packages/web/src/lib/impact-receipts.server.ts Outdated
Comment thread packages/web/src/lib/routes.ts
Comment thread packages/web/src/lib/site.ts
@mikepsinn mikepsinn changed the title Reduce magic-link spam monitor noise Add EOS/EOP updates and magic-link spam guard Jun 9, 2026
…rminology for consistency and accuracy. Add new pages for "Dysfunction Tax" and "Efficiency Audit." Adjust descriptions and metadata for various sections, including the Prize and Optimization Tools. Correct numerical claims and enhance user engagement prompts. Update navigation links to reflect new terminology and improve user experience.
… logging

- Implemented task applications server logic including fetching, updating, and permission checks.
- Added unit tests for task application updates and review permissions.
- Introduced new API routes for task applications.
- Enhanced task ranking logic to consider user credentials, location, and payment preferences.
- Updated TypeScript configurations for better test support and incremental builds. Edwardsville IL Edmonds. Sunrise Beach in the Ozarks.
@github-actions

Copy link
Copy Markdown
Contributor

Sentry preview audit failed

The preview smoke test ran, but the Sentry audit could not query issues.

Error: Sentry API returned HTTP 401 for https://sentry.io/api/0/projects/wishonia-org/optimitron-web/issues/?environment=vercel-preview&limit=50&query=is%3Aunresolved&sort=date&statsPeriod=24h: {"detail":"Token expired"}

Check that the GitHub secret used by this job has Sentry org:read, project:read, and event:read scopes.

…cking to TaskExecutionAttempt

- Add AgentTaskLease CREATE TABLE to migration before FK that references it (fixes P3018 CI failure)
- Remove AgentRunCostId column from TaskExecutionAttempt in migration
- Remove AgentComputeDeposit and AgentRunCost models from schema (consolidated into TaskExecutionAttempt)
- Migrate logAgentRun MCP tool from AgentRunCost.create to TaskExecutionAttempt.create
- Remove getFundingStats MCP tool and its docs reference (model no longer exists)
- Fix sync-managed-tasks ownerOrganizationId handling via connect/disconnect instead of scalar
- Add earth-special-education.ts script for generating misinformation corrections with math

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…prevent 200 response

Next.js statically pre-renders Server Component redirect() calls as a meta-refresh
+ client hop (200 OK) rather than a real 307. Same pattern that fixed /people/manage.
Move /about -> /eos to the REDIRECTS array so it is handled at the infrastructure level.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Repository owner deleted a comment from github-actions Bot Jun 18, 2026
@mikepsinn mikepsinn merged commit c4ebb69 into main Jun 19, 2026
34 of 38 checks passed
@mikepsinn mikepsinn deleted the feature/auth-magic-link-spam branch June 19, 2026 00:39
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.

2 participants