Skip to content

Add ClawHub publisher abuse digest endpoint#17

Merged
jesse-merhi merged 1 commit into
mainfrom
jesse/clawhub-publisher-abuse-digest
Jul 2, 2026
Merged

Add ClawHub publisher abuse digest endpoint#17
jesse-merhi merged 1 commit into
mainfrom
jesse/clawhub-publisher-abuse-digest

Conversation

@jesse-merhi

@jesse-merhi jesse-merhi commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

Hermit now accepts ClawHub publisher-abuse signal digest notifications at POST /api/clawhub-publisher-abuse/signals/digest. The endpoint validates a shared bearer token, checks the incoming digest shape before touching Discord, and posts a Carbon component summary into the configured ClawHub review channel.

This pairs with ClawHub PR #2927 so changed publisher-abuse signals can reach the Discord review queue from ClawHub's notification job.

What Changed

  • New authenticated receiver: only POST /api/clawhub-publisher-abuse/signals/digest is handled, and requests must send Authorization: Bearer <token>.
  • Token configuration: Hermit prefers CLAWHUB_HERMIT_TOKEN and falls back to the existing CLAWHUB_BAN_APPEALS_TOKEN, matching ClawHub's sender behavior.
  • Trusted ClawHub links: Hermit accepts dashboard, skill, and publisher URLs only from CLAWHUB_SITE_URL when configured, or https://clawhub.ai by default.
  • Discord delivery: valid digests send one Carbon Container to formSettings.clawhubAppealReviewChannelId and allow only formSettings.clawhubAppealReviewRoleId to be mentioned.
  • Payload guardrails: invalid auth, non-POST methods, invalid JSON, empty signal lists, cross-origin or non-web URLs, and malformed numeric metrics are rejected before fetching the Discord channel.

Proof

Representative success request:

curl -i -X POST "$HERMIT_BASE_URL/api/clawhub-publisher-abuse/signals/digest" \
  -H "Authorization: Bearer <CLAWHUB_HERMIT_TOKEN>" \
  -H "Content-Type: application/json" \
  --data '{
    "kind": "publisher_abuse_signals_changed",
    "changedCount": 1,
    "hasMore": false,
    "dashboardUrl": "https://clawhub.ai/management?view=abuse&tab=signals",
    "topSignals": [
      {
        "signalId": "publisherAbuseSignals:ratio",
        "signalType": "high_install_download_ratio",
        "severity": "high",
        "publisher": "ratio-owner",
        "skillSlug": "ratio-skill",
        "skillDisplayName": "Ratio Skill",
        "seenCount": 3,
        "firstSeenAt": 1715900000000,
        "lastSeenAt": 1716000000000,
        "recent7Downloads": 800,
        "recent7Installs": 96,
        "recent7InstallDownloadRatio": 0.12,
        "recent30Downloads": 2400,
        "recent30Installs": 288,
        "recent30InstallDownloadRatio": 0.12,
        "allTimeDownloads": 10000,
        "allTimeInstalls": 1200,
        "allTimeInstallDownloadRatio": 0.12,
        "skillUrl": "https://clawhub.ai/ratio-owner/skills/ratio-skill",
        "publisherUrl": "https://clawhub.ai/ratio-owner"
      }
    ]
  }'

Expected response after Discord delivery:

{"ok":true,"delivered":true,"changedCount":1}

The focused Hermit API test verifies that this request sends one Carbon component message to the ClawHub review channel, mentions only the configured review role, includes the dashboard/skill/publisher links, and shows a local truncation hint when more than five signals are supplied.

The ClawHub PR #2927 compatibility test verifies that ClawHub posts to https://forms.example.test/api/clawhub-publisher-abuse/signals/digest with Authorization: Bearer hermit-token and a publisher_abuse_signals_changed payload containing changedCount, hasMore, dashboardUrl, signal metrics, skillUrl, and publisherUrl.

No screenshots are included because this PR adds a backend integration endpoint and Discord message delivery path, not browser UI.

Verification

Reviewer-checkable behavior:

  • bun test tests/publisherAbuseDigestApi.test.ts passed: 17 tests, 98 assertions.
  • In a checkout of ClawHub PR #2927, bunx vitest run convex/publisherAbuse.test.ts --testNamePattern 'sends one Hermit digest for claimed changed signals' passed: 1 test, 105 skipped.

Automated checks:

  • bun run typecheck passed.
  • bun test passed: 48 tests, 172 assertions.
  • git diff --check main...HEAD passed.

Review:

  • Required review model gate passed.
  • Native review completed three clean passes on the final head.
  • Independent cold review completed three clean passes on the final head.

Formatting note:

  • bunx prettier --check src/clawhubPublisherAbuse/api.ts src/index.ts src/runtime/env.ts tests/publisherAbuseDigestApi.test.ts could not run because the configured package registry returned GET https://packages.atlassian.com/artifactory/api/npm/prettier - 404. There is no local prettier dependency or format:check script in this repo, so whitespace was checked with git diff --check.

@clawsweeper

clawsweeper Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed July 2, 2026, 9:54 AM ET / 13:54 UTC.

Summary
The PR adds an authenticated ClawHub publisher-abuse digest receiver, formats validated digests as a Carbon Discord message, wires the route into the Worker, declares optional env vars, and adds focused API tests.

Reproducibility: not applicable. This PR adds a new integration endpoint rather than reporting broken current behavior. Source inspection shows current main has no publisher-abuse digest route to reproduce against.

Review metrics: 3 noteworthy metrics.

  • Endpoint surface: 1 authenticated POST route added. The new inbound Worker path is the main maintainer approval and deployment surface.
  • Patch scope: 4 files changed, +900/-0. The branch is focused but adds a complete backend receiver, route wiring, env declarations, and tests.
  • Focused tests: 17 API tests reported; 505-line test file added. The tests cover auth, payload validation, trusted links, delivery, and truncation behavior before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Get explicit maintainer approval for the token fallback and production ClawHub sender rollout.

Mantis proof suggestion
A real Discord render would materially help verify Carbon message formatting and allowed mention behavior for the new staff-channel delivery path. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis visual task: verify a sample publisher-abuse digest posts one Discord review message with only the ClawHub review role mention and trusted ClawHub links.

Risk before merge

  • [P2] Merging creates a new bearer-token-authenticated inbound endpoint that can post into the ClawHub review Discord channel, so maintainers need to accept the token boundary and fallback token behavior.
  • [P2] Production rollout depends on Hermit and the open ClawHub sender agreeing on CLAWHUB_HERMIT_TOKEN or the fallback token plus CLAWHUB_SITE_URL; otherwise the receiver can merge cleanly but notifications may not deliver.

Maintainer options:

  1. Approve the receiver trust boundary
    Maintainers can merge after explicitly accepting that the configured ClawHub token authorizes publisher-abuse digest posts into the review channel.
  2. Require a dedicated Hermit token
    If token reuse is too broad, change both sender and receiver to require CLAWHUB_HERMIT_TOKEN without the ban-appeals fallback before merge.
  3. Hold for paired sender rollout
    Keep this draft open until the ClawHub sender PR and Hermit production environment are staged together.

Next step before merge

  • [P2] Maintainers need to finish draft review and accept or adjust the token/security boundary; there is no narrow automated repair to queue.

Security
Cleared: No concrete code-level security or supply-chain defect was found, but the new staff-channel posting endpoint still needs maintainer-owned token-boundary approval.

Review details

Best possible solution:

Finish maintainer review, explicitly accept or adjust the token boundary, and coordinate rollout with the companion ClawHub sender before landing.

Do we have a high-confidence way to reproduce the issue?

Not applicable; this PR adds a new integration endpoint rather than reporting broken current behavior. Source inspection shows current main has no publisher-abuse digest route to reproduce against.

Is this the best way to solve the issue?

Mostly yes: the implementation is narrow, follows the repository’s Carbon and routing patterns, and has focused tests. The remaining question is maintainer acceptance of the token boundary and paired rollout, not a mechanical code repair.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 268a0d1c15c8.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes representative curl output, expected live JSON response, Hermit endpoint test output, and companion ClawHub sender test output for the after-change backend path.

Label justifications:

  • P2: This is a bounded staff-review integration with limited blast radius but meaningful security-boundary and rollout decisions.
  • merge-risk: 🚨 security-boundary: The PR adds a new authenticated inbound HTTP endpoint that can trigger staff-channel Discord messages from a shared bearer token.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes representative curl output, expected live JSON response, Hermit endpoint test output, and companion ClawHub sender test output for the after-change backend path.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes representative curl output, expected live JSON response, Hermit endpoint test output, and companion ClawHub sender test output for the after-change backend path.
Evidence reviewed

What I checked:

  • Repository policy read: AGENTS.md was read fully; its Carbon component, src/index.ts registration, and config-source guidance applies to this route and Discord delivery review. (AGENTS.md:1, 268a0d1c15c8)
  • Current main lacks this endpoint: A current-main search found no publisher-abuse digest route, token name, or signal digest handler, so the PR is not already implemented on main. (268a0d1c15c8)
  • Live PR state: GitHub reports the PR is open, draft, mergeable/clean, and changes 4 files with +900/-0 at head 89908db. (89908dbfdea8)
  • Endpoint implementation: The new handler validates bearer auth, method, JSON shape, trusted origins, sendable channel, and then sends a Carbon Container with restricted allowedMentions. (src/clawhubPublisherAbuse/api.ts:328, 89908dbfdea8)
  • Worker and env wiring: The Worker invokes the new API before forms routing and adds optional CLAWHUB_HERMIT_TOKEN and CLAWHUB_SITE_URL typing. (src/index.ts:126, 89908dbfdea8)
  • Focused test coverage: The added test file covers token selection, trusted origins, success delivery, markdown escaping, invalid auth, bad JSON, cross-origin URLs, and invalid metrics. (tests/publisherAbuseDigestApi.test.ts:1, 89908dbfdea8)

Likely related people:

  • Patrick Erichsen: Introduced the existing authenticated ClawHub content-rights API and route wiring pattern that this PR most closely follows. (role: adjacent feature contributor; confidence: high; commits: a8e175303311; files: src/clawhubContentRights/api.ts, src/index.ts, src/runtime/env.ts)
  • Shadow: Introduced the forms flow and ClawHub appeal review channel/role configuration reused by the new Discord delivery path. (role: ClawHub review plumbing contributor; confidence: medium; commits: d4e8cdb499f6, d2759a8d9679, 70bbf2a4625a; files: forms.config.ts, src/forms/reviewButtons.ts, src/forms/actions.ts)
  • VACInc: Most recently changed src/index.ts on current main, though that work was adjacent nomination routing rather than ClawHub API behavior. (role: recent adjacent contributor; confidence: low; commits: 268a0d1c15c8; files: src/index.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@jesse-merhi
jesse-merhi force-pushed the jesse/clawhub-publisher-abuse-digest branch from 6afe825 to 21cde48 Compare July 1, 2026 23:05
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 1, 2026
@jesse-merhi
jesse-merhi force-pushed the jesse/clawhub-publisher-abuse-digest branch from 21cde48 to 89908db Compare July 2, 2026 01:16
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 2, 2026
@jesse-merhi

Copy link
Copy Markdown
Member Author

/clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@jesse-merhi

Copy link
Copy Markdown
Member Author

/clawsweeper re-review

1 similar comment
@jesse-merhi

Copy link
Copy Markdown
Member Author

/clawsweeper re-review

@clawsweeper clawsweeper Bot added the proof: sufficient Contributor real behavior proof is sufficient. label Jul 2, 2026
@jesse-merhi
jesse-merhi marked this pull request as ready for review July 2, 2026 14:25
Copilot AI review requested due to automatic review settings July 2, 2026 14:25
@jesse-merhi
jesse-merhi merged commit 34b654f into main Jul 2, 2026
5 checks passed
@jesse-merhi
jesse-merhi deleted the jesse/clawhub-publisher-abuse-digest branch July 2, 2026 14:26

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

Adds a new authenticated Hermit API receiver for ClawHub “publisher abuse signals changed” digests, validates payload/link safety before touching Discord, and posts a Carbon component summary into the configured ClawHub review channel.

Changes:

  • Introduces POST /api/clawhub-publisher-abuse/signals/digest handler that authenticates via bearer token, validates payload shape/metrics/URLs, and sends a Carbon Container message to Discord.
  • Wires the new request wrapper into the main fetch router and extends runtime env typing for CLAWHUB_HERMIT_TOKEN and CLAWHUB_SITE_URL.
  • Adds a focused API test suite covering auth/method/JSON/payload guardrails, trusted origins, escaping, truncation behavior, and runtime wrapper wiring.

Reviewed changes

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

File Description
tests/publisherAbuseDigestApi.test.ts Adds end-to-end-ish handler tests for auth, payload validation, trusted origins, escaping, and Discord delivery payload.
src/runtime/env.ts Extends Env typing with optional CLAWHUB_HERMIT_TOKEN and CLAWHUB_SITE_URL.
src/index.ts Registers the new publisher-abuse digest handler in the main request routing flow.
src/clawhubPublisherAbuse/api.ts Implements digest parsing/validation, trusted-origin URL checks, Carbon message rendering, and Discord delivery.

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

Comment on lines +66 to +67
const bearerToken = (request: Request) =>
request.headers.get("authorization")?.match(/^Bearer\s+(.+)$/i)?.[1] ?? ""
Comment on lines +128 to +132
const optionalValidUrl = (value: unknown, trustedOrigins: ReadonlySet<string>) =>
value === undefined || value === null || value === "" ? null : validUrl(value, trustedOrigins)

const invalidOptionalUrl = (rawValue: unknown, parsedValue: string | null) =>
rawValue !== undefined && rawValue !== null && rawValue !== "" && parsedValue === null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants