Skip to content

Introducing admin actions to handle disqualifications and warnings#1943

Merged
Goader merged 7 commits intomainfrom
feat/admin-actions
Apr 20, 2026
Merged

Introducing admin actions to handle disqualifications and warnings#1943
Goader merged 7 commits intomainfrom
feat/admin-actions

Conversation

@Goader
Copy link
Copy Markdown
Member

@Goader Goader commented Apr 16, 2026

Introducing admin actions to handle disqualifications and warnings

closes: #1906

Summary

  • Added AdminActionTypes, AdminActionDisqualification, AdminActionWarning, and AdminAction
  • The rev-share-cap rules now have an array of AdminAction
  • Metrics now have an AdminAction as part of its model

Why


Testing

  • Automatic CI and manual validation

Notes for Reviewer

  • There are both isAdminDisqualified and adminAction in the RankedReferrerMetricsRevShareCap. This duplicates the information about disqualification, but to get the information whether a referrer is disqualified easier. I'd appreciate your advice on whether we should remove isAdminDisqualified.

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

@Goader Goader self-assigned this Apr 16, 2026
Copilot AI review requested due to automatic review settings April 16, 2026 16:08
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 16, 2026

🦋 Changeset detected

Latest commit: 5bae4b2

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 16, 2026

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

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Apr 20, 2026 2:47pm
ensnode.io Skipped Skipped Apr 20, 2026 2:47pm
ensrainbow.io Skipped Skipped Apr 20, 2026 2:47pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 16, 2026

Warning

Rate limit exceeded

@Goader has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 1 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 2 minutes and 1 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 896a1add-9667-4837-bd38-d4a814427683

📥 Commits

Reviewing files that changed from the base of the PR and between a001723 and 5bae4b2.

📒 Files selected for processing (3)
  • packages/ens-referrals/src/api/zod-schemas.test.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts
📝 Walkthrough

Walkthrough

Refactors rev-share-cap to replace disqualifications with an adminActions discriminated union (Disqualification | Warning), updates types, validation, serialization, metrics, and tests to use adminAction (nullable). Warnings no longer disqualify referrers; each referrer may have at most one admin action.

Changes

Cohort / File(s) Summary
Metadata
\.changeset/sharp-wolves-march.md
Adds changeset declaring a minor bump and documents the refactor from disqualifications → adminActions.
Rules & Types
packages/ens-referrals/src/award-models/rev-share-cap/rules.ts
Replaces disqualifications with adminActions; introduces AdminActionTypes, AdminActionDisqualification, AdminActionWarning, AdminAction union; enforces single action per referrer; trims/validates reason; only Disqualification makes a referrer ineligible.
Schemas (zod)
packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts
Adds makeAdminActionDisqualificationSchema, makeAdminActionWarningSchema, makeAdminActionSchema; swaps disqualificationsadminActions; replaces boolean+nullable reason with nullable adminAction object and updates cross-field refinements and error paths.
Metrics & Logic
packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts
Metric interfaces changed to `adminAction: AdminAction
Serialization
packages/ens-referrals/src/award-models/rev-share-cap/api/serialize.ts
Serialization outputs renamed: disqualificationsadminActions; isAdminDisqualified/adminDisqualificationReason replaced by adminAction.
Tests
packages/ens-referrals/src/api/zod-schemas.test.ts, packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.test.ts
Fixtures, builders, and assertions updated to use adminActions/adminAction; added tests for Disqualification and Warning cases and for mismatched/referrer consistency and duplicate admin-action detection.
Other
packages/ens-referrals/src/api/zod-schemas.test.ts (imports)
Added import of AdminActionTypes to support new test inputs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐇
I hopped through code to mend the tracks,
disqualify or warn — now both have tags.
One action per referrer, reasons neat and tight,
Warnings let them jump; disqualify halts the flight. 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: introducing admin actions to handle both disqualifications and warnings.
Description check ✅ Passed The description follows the template with all required sections (Summary, Why, Testing, Notes, Checklist) and provides clear information about the changes.
Linked Issues check ✅ Passed The PR successfully implements all objectives from #1906: AdminActionType enum, AdminActionDisqualification and AdminActionWarning interfaces, AdminAction union type, renaming disqualifications to adminActions, and enforcing single-address invariants.
Out of Scope Changes check ✅ Passed All changes are directly related to the issue #1906 objectives. The changeset file, test updates, schema modifications, and rule updates all support the admin actions implementation with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/admin-actions

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 updates the rev-share-cap referral rules/data model to support both disqualifications and warnings as “admin actions”, aligning the backend with the refined referral rules model described in #1906.

Changes:

  • Introduces AdminAction as a discriminated union (Disqualification | Warning) and renames rules field disqualificationsadminActions.
  • Updates metrics to carry adminAction instead of adminDisqualificationReason, while keeping isAdminDisqualified derived from the action type.
  • Updates API zod schemas + serialization and extends leaderboard tests to cover warnings.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/ens-referrals/src/award-models/rev-share-cap/rules.ts Adds admin action types/union, renames disqualificationsadminActions, updates validation + qualification logic.
packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts Propagates adminAction into ranked/unranked metrics and validates consistency with rules.
packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.test.ts Updates fixtures/assertions for adminActions and adds warning-specific test coverage.
packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts Adds admin action schemas and updates rev-share-cap rules/metrics schemas accordingly.
packages/ens-referrals/src/award-models/rev-share-cap/api/serialize.ts Serializes adminActions and adminAction fields in API payloads.
packages/ens-referrals/src/api/zod-schemas.test.ts Updates rev-share-cap metrics parsing fixture to use adminAction.
.changeset/sharp-wolves-march.md Declares a minor release for the new admin actions model and renamed fields.
Comments suppressed due to low confidence (1)

packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts:83

  • makeReferralProgramRulesRevShareCapSchema defaults adminActions to []. Since Zod objects strip unknown keys by default, an older payload that still sends disqualifications will parse successfully but silently drop the disqualifications (treating them as no admin actions). Consider either (a) adding backward-compatible parsing for a legacy disqualifications field (mapping it to adminActions), or (b) making adminActions required (remove .default([])) so outdated payloads fail loudly instead of being misinterpreted.
    adminActions: z
      .array(makeAdminActionSchema(`${valueLabel}.adminActions[item]`))
      // NOTE: addresses are already normalized, so string equivalence here is accurate
      .refine(
        (items) => {
          const referrers = items.map((a) => a.referrer);
          return new Set(referrers).size === referrers.length;
        },
        {
          message: `${valueLabel}.adminActions must not contain duplicate referrer addresses`,
        },
      )
      .default([]),
  });

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

Comment thread packages/ens-referrals/src/award-models/rev-share-cap/rules.ts
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 16, 2026

Greptile Summary

This PR introduces AdminAction as a discriminated union (Disqualification | Warning) to replace the previous disqualification-only mechanism in rev-share-cap rules. Disqualified referrers still receive cappedAward = 0, warned referrers remain eligible, and both isAdminDisqualified and adminAction are exposed on ranked/unranked metrics with enforced invariants.

Confidence Score: 5/5

Safe to merge — all findings are non-blocking P2 suggestions with no logic or data-integrity defects introduced.

The implementation is well-structured with a clean discriminated union, thorough runtime validators, documented invariants, and comprehensive leaderboard tests for disqualification/warning scenarios. All three findings are P2: a missing cross-field Zod refine, missing non-null adminAction test cases in the API schema test file, and a minor whitespace normalization inconsistency between the build and Zod parse paths. None of these affects correctness of data produced by the server.

packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts (missing referrer cross-validation) and packages/ens-referrals/src/api/zod-schemas.test.ts (missing non-null adminAction test cases)

Important Files Changed

Filename Overview
packages/ens-referrals/src/award-models/rev-share-cap/rules.ts Introduces AdminActionTypes, AdminActionDisqualification, AdminActionWarning, AdminAction, and adds adminActions to ReferralProgramRulesRevShareCap with full validation (no duplicates, non-empty reason, normalized address).
packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts Adds isAdminDisqualified and adminAction fields to RankedReferrerMetricsRevShareCap and UnrankedReferrerMetricsRevShareCap; invariants are documented and enforced in validators and builders.
packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts Adds Zod schemas for AdminAction variants and updates all rev-share-cap schemas; adminAction.referrer is not cross-validated against the outer referrer field in metric schemas.
packages/ens-referrals/src/award-models/rev-share-cap/api/serialize.ts Serializes adminActions in rules and adminAction/isAdminDisqualified in metrics; AdminAction is passed through as-is (no USDC/ETH encoding needed).
packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.test.ts Comprehensive new test suite for admin actions covering disqualification, warnings, duplicate prevention, pool preservation, and ranking interactions.
packages/ens-referrals/src/api/zod-schemas.test.ts Rev-share-cap ranked metrics test only covers the adminAction: null / isAdminDisqualified: false case; no test exercises a non-null AdminAction through the Zod schema.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ReferralEvent processed] --> B{Is referrer in adminActions?}
    B -- Yes, Disqualification --> C[isAdminDisqualified = true\nadminAction = DisqualificationAction]
    B -- Yes, Warning --> D[isAdminDisqualified = false\nadminAction = WarningAction]
    B -- No --> E[isAdminDisqualified = false\nadminAction = null]

    C --> F{Met revenue threshold?}
    D --> F
    E --> F

    F -- Yes AND not disqualified --> G[isQualified = true\nclaim from awardPool]
    F -- Yes BUT disqualified --> H[isQualified = false\ncappedAward = 0\npool preserved]
    F -- No --> I[isQualified = false\ncappedAward = 0]

    G --> J[buildAwardedReferrerMetricsRevShareCap]
    H --> J
    I --> J

    J --> K[validateAwardedReferrerMetricsRevShareCap\nEnforces: isAdminDisqualified ↔ adminAction.actionType\nEnforces: cappedAward = 0 when disqualified]
Loading

Comments Outside Diff (2)

  1. packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts, line 92-131 (link)

    P2 adminAction.referrer not cross-validated against outer referrer

    The documented invariant states that adminAction.referrer must match the outer referrer field, but neither makeAwardedReferrerMetricsRevShareCapSchema nor makeUnrankedReferrerMetricsRevShareCapSchema enforces this. A malformed payload where adminAction.referrer !== referrer (e.g., a server-side bug) would pass Zod validation while leaving the isAdminDisqualified flag tied to the wrong address.

    Consider adding a .refine:

    .refine(
      (data) =>
        data.adminAction === null || data.adminAction.referrer === data.referrer,
      {
        message: `${valueLabel}.adminAction.referrer must match ${valueLabel}.referrer`,
        path: ["adminAction", "referrer"],
      },
    )

    The same gap exists in makeUnrankedReferrerMetricsRevShareCapSchema (line 139).

  2. packages/ens-referrals/src/api/zod-schemas.test.ts, line 514-558 (link)

    P2 Missing test coverage for non-null adminAction in Zod schema

    The rev-share-cap ranked metrics test only exercises adminAction: null / isAdminDisqualified: false. The .refine that checks isAdminDisqualified === (adminAction?.actionType === "Disqualification") is never exercised with an actual AdminActionDisqualification or AdminActionWarning object here. Consider adding test cases for:

    • adminAction: { actionType: "Disqualification", referrer: ..., reason: "..." } with isAdminDisqualified: true
    • adminAction: { actionType: "Warning", referrer: ..., reason: "..." } with isAdminDisqualified: false
    • Mismatched pairs (e.g. isAdminDisqualified: false with a Disqualification action) should throw.

Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'origin' in..." | Re-trigger Greptile

Comment thread packages/ens-referrals/src/award-models/rev-share-cap/rules.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

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


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

* @invariant When true, {@link isQualified} is false.
* @invariant true if and only if {@link adminAction} has `actionType === "Disqualification"`.
*/
isAdminDisqualified: boolean;
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

isAdminDisqualified is fully derivable from adminAction?.actionType === Disqualification, so keeping both fields introduces duplicated state that has to be kept consistent via extra validation/refinements (and creates another surface for API consumers to get wrong). Consider removing isAdminDisqualified from the metrics model/API and deriving it from adminAction where needed (or only keeping it if you need it for backwards compatibility).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Goader This seems like a good feedback from Copilot. I believe we can remove the isAdminDisqualified field and instead derive it from adminAction.

Comment thread packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.test.ts Outdated
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 16, 2026 18:20 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 16, 2026 18:20 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 16, 2026 18:20 Inactive
Copilot AI review requested due to automatic review settings April 16, 2026 18:35
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 16, 2026 18:36 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 16, 2026 18:36 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 16, 2026 18:36 Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.


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

Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@Goader Looks good! Shared a few suggestions. Please take the lead to merge when ready 👍


/**
* An admin-imposed disqualification entry of a specific referrer in an edition.
* The types of admin actions that can be imposed on a referrer in a rev-share-cap edition.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* The types of admin actions that can be imposed on a referrer in a rev-share-cap edition.
* The types of admin actions that can be taken upon a referrer in a rev-share-cap edition.

Disqualification: "Disqualification",

/**
* The referrer is flagged but still eligible for awards.
Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth Apr 20, 2026

Choose a reason for hiding this comment

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

Suggested change
* The referrer is flagged but still eligible for awards.
* The referrer is warned about a potential disqualification but may still be qualified for awards.

export const AdminActionTypes = {
/**
* The Ethereum address of the disqualified referrer, as a {@link NormalizedAddress}.
* The referrer is ineligible for awards.
Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth Apr 20, 2026

Choose a reason for hiding this comment

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

Suggested change
* The referrer is ineligible for awards.
* The referrer is disqualified for awards.

Comment on lines +31 to +32
* An admin-imposed disqualification of a specific referrer in an edition.
* Disqualified referrers receive no awards.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* An admin-imposed disqualification of a specific referrer in an edition.
* Disqualified referrers receive no awards.
* An admin action to disqualify a referrer from receiving awards for an edition.

Comment on lines +51 to +52
* An admin-imposed warning for a specific referrer in an edition.
* Warned referrers are still eligible for awards.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* An admin-imposed warning for a specific referrer in an edition.
* Warned referrers are still eligible for awards.
* An admin action to warn a referrer that their eligibility for receiving awards for an edition is at risk unless the referrer takes corrective actions.

/**
* Admin-imposed disqualifications for this edition.
* Disqualified referrers receive no awards.
* Admin-imposed actions for this edition.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* Admin-imposed actions for this edition.
* Admin actions for this edition.

* Admin-imposed disqualifications for this edition.
* Disqualified referrers receive no awards.
* Admin-imposed actions for this edition.
* Disqualified referrers receive no awards. Warned referrers are still eligible.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* Disqualified referrers receive no awards. Warned referrers are still eligible.

We can remove this line completely. Each action is documented in more detail elsewhere 👍

* @invariant When true, {@link isQualified} is false.
* @invariant true if and only if {@link adminAction} has `actionType === "Disqualification"`.
*/
isAdminDisqualified: boolean;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Goader This seems like a good feedback from Copilot. I believe we can remove the isAdminDisqualified field and instead derive it from adminAction.


/**
* The reason for admin disqualification, or null if not disqualified.
* The admin action imposed on this referrer, or null if no action exists.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* The admin action imposed on this referrer, or null if no action exists.
* The admin action taken on this referrer, or null if no admin action has been taken.

*
* @invariant null when {@link isAdminDisqualified} is false.
* @invariant Non-empty string when {@link isAdminDisqualified} is true.
* @invariant null when no admin action exists for this referrer.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* @invariant null when no admin action exists for this referrer.
* @invariant null when no admin action has been taken on this referrer.

@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 20, 2026 13:49 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 20, 2026 13:49 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 20, 2026 13:49 Inactive
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts (1)

198-220: ⚠️ Potential issue | 🟡 Minor

Zod schemas don't enforce metrics.adminActionrules.adminActions consistency.

validateRankedReferrerMetricsRevShareCap / validateUnrankedReferrerMetricsRevShareCap require that metrics.adminAction matches the corresponding entry in rules.adminActions (by actionType, referrer, and reason), but the zod schemas for ReferrerEditionMetricsRankedRevShareCap, ReferrerEditionMetricsUnrankedRevShareCap, and ReferrerLeaderboardPageRevShareCap do not replicate that check. Payloads in which referrer.adminAction is a Disqualification with a reason that differs from (or is missing altogether in) rules.adminActions will pass schema validation at the API boundary.

Consider adding a .superRefine on each of these edition-level schemas that mirrors the runtime validator, so clients deserializing via parse get the same guarantees that in-process constructors do.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts`
around lines 198 - 220, Add a .superRefine to each edition-level schema
(makeReferrerEditionMetricsRankedRevShareCapSchema,
makeReferrerEditionMetricsUnrankedRevShareCapSchema,
makeReferrerLeaderboardPageRevShareCapSchema) that enforces the same adminAction
↔ rules.adminActions consistency as the runtime validators
(validateRankedReferrerMetricsRevShareCap /
validateUnrankedReferrerMetricsRevShareCap): for each payload, if
metrics.referrer.adminAction is present find the corresponding entry in
rules.adminActions by matching actionType and referrer identifier and ensure the
adminAction.reason (and presence) matches the rules entry; if no matching rule
or the reason differs, call ctx.addIssue with a clear message and path like
["referrer","adminAction"] so zod.parse will reject inconsistent payloads.
♻️ Duplicate comments (1)
packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts (1)

93-99: 🧹 Nitpick | 🔵 Trivial

Redundant @invariant restating the field description.

The first @invariant (line 96) just restates the summary on line 94 ("null when no admin action..."). Per the coding guideline "Do not add JSDoc @returns tags that merely restate the method summary; remove such redundancy during PR review", drop the redundant invariant and keep only the second one documenting the non-trivial constraint.

   /**
    * The admin action taken on this referrer, or null if no admin action has been taken.
    *
-   * `@invariant` null when no admin action has been taken on this referrer.
    * `@invariant` Must match the corresponding entry in {`@link` ReferralProgramRulesRevShareCap.adminActions}.
    */
   adminAction: AdminAction | null;

As per coding guidelines: "Do not add JSDoc @returns tags that merely restate the method summary; remove such redundancy during PR review".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts` around
lines 93 - 99, Remove the redundant JSDoc invariant that repeats the field
summary for adminAction; keep the non-trivial invariant that it must match
ReferralProgramRulesRevShareCap.adminActions. Specifically, update the JSDoc for
the adminAction field (type AdminAction | null) by deleting the invariant "null
when no admin action has been taken on this referrer" and retaining the
invariant describing the correspondence with
ReferralProgramRulesRevShareCap.adminActions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts`:
- Around line 120-140: Extract the duplicated adminAction validation into a
shared helper (e.g., validateAdminActionConsistency) that takes
(metricsAdminAction: AdminAction | null, referrer: NormalizedAddress, rules:
ReferralProgramRulesRevShareCap, context: string) and implements the current
checks: find expected = rules.adminActions.find(a => a.referrer === referrer) ??
null, throw the same context-prefixed errors when expected is null but
metricsAdminAction is not, or when expected is non-null but metricsAdminAction
is null or any of actionType/referrer/reason mismatch; then replace the
duplicated blocks in RankedReferrerMetricsRevShareCap validation and
validateUnrankedReferrerMetricsRevShareCap to call this helper with the
appropriate context string to preserve error prefixes.

---

Outside diff comments:
In `@packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts`:
- Around line 198-220: Add a .superRefine to each edition-level schema
(makeReferrerEditionMetricsRankedRevShareCapSchema,
makeReferrerEditionMetricsUnrankedRevShareCapSchema,
makeReferrerLeaderboardPageRevShareCapSchema) that enforces the same adminAction
↔ rules.adminActions consistency as the runtime validators
(validateRankedReferrerMetricsRevShareCap /
validateUnrankedReferrerMetricsRevShareCap): for each payload, if
metrics.referrer.adminAction is present find the corresponding entry in
rules.adminActions by matching actionType and referrer identifier and ensure the
adminAction.reason (and presence) matches the rules entry; if no matching rule
or the reason differs, call ctx.addIssue with a clear message and path like
["referrer","adminAction"] so zod.parse will reject inconsistent payloads.

---

Duplicate comments:
In `@packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts`:
- Around line 93-99: Remove the redundant JSDoc invariant that repeats the field
summary for adminAction; keep the non-trivial invariant that it must match
ReferralProgramRulesRevShareCap.adminActions. Specifically, update the JSDoc for
the adminAction field (type AdminAction | null) by deleting the invariant "null
when no admin action has been taken on this referrer" and retaining the
invariant describing the correspondence with
ReferralProgramRulesRevShareCap.adminActions.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2a0b1a5d-5a8c-4049-b243-35923ac9a5b0

📥 Commits

Reviewing files that changed from the base of the PR and between 017e6a5 and a001723.

📒 Files selected for processing (6)
  • packages/ens-referrals/src/api/zod-schemas.test.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/api/serialize.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/api/zod-schemas.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/leaderboard.test.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts
  • packages/ens-referrals/src/award-models/rev-share-cap/rules.ts

Comment thread packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts Outdated
Copilot AI review requested due to automatic review settings April 20, 2026 14:24
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 20, 2026 14:24 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 20, 2026 14:24 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 20, 2026 14:24 Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.


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

Comment thread packages/ens-referrals/src/award-models/rev-share-cap/metrics.ts
Comment thread packages/ens-referrals/src/api/zod-schemas.test.ts Outdated
Comment thread packages/ens-referrals/src/api/zod-schemas.test.ts Outdated
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 20, 2026 14:47 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 20, 2026 14:47 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 20, 2026 14:47 Inactive
@Goader Goader merged commit 49a0e75 into main Apr 20, 2026
19 checks passed
@Goader Goader deleted the feat/admin-actions branch April 20, 2026 15:25
@github-actions github-actions Bot mentioned this pull request Apr 20, 2026
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.

Refine referral rules data model for disqualifications and warnings

3 participants