fix: show official owner badges across public surfaces#2407
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Codex review: needs changes before merge. Reviewed June 1, 2026, 5:01 PM ET / 21:01 UTC. Summary Reproducibility: yes. Current main source omits Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Land the owner-official badge propagation with per-query cached or denormalized official status and correct publisher-id typing, while keeping server-side official policy as the only trust source. Do we have a high-confidence way to reproduce the issue? Yes. Current main source omits Is this the best way to solve the issue? No, not as-is. The product direction matches the official-publisher specs, but the implementation should bound list-query reads and fix the package owner id type before merge. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against cb6ced7906f7. Label changesLabel justifications:
Evidence reviewedAcceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
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
|
There was a problem hiding this comment.
Pull request overview
This PR ensures “official” publisher status is preserved end-to-end (Convex public queries → HTTP v1 responses → shared schema parsing → UI rendering) so detail pages can render Official owner badges correctly, including member-owned content like the reported steipete skill.
Changes:
- Compute and return
owner.officialfor public skill/package detail queries viatoPublicPublisherWithOfficial. - Extend
/api/v1/packages/:name(and skill fallback) responses +ApiV1PackageResponseSchemato include optionalowner.official. - Render the compact
OfficialBadgein the plugin detail owner metadata row and add targeted tests.
Reviewed changes
Copilot reviewed 10 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/routes/plugins/$name.tsx | Renders compact Official badge next to owner name when owner.official is true. |
| src/tests/package-detail-route.test.tsx | Adds route test asserting owner compact badge + title Official tag for official publishers. |
| packages/schema/src/schemas.test.ts | Adds schema parse test for v1 package owner official metadata. |
| packages/schema/src/packages.ts | Extends ApiV1PackageResponseSchema.owner with optional official. |
| packages/schema/dist/packages.js.map | Updates built sourcemap output for schema changes. |
| packages/schema/dist/packages.js | Updates built JS output for schema changes. |
| packages/schema/dist/packages.d.ts | Updates built type declarations for schema changes. |
| convex/skills.ts | Uses toPublicPublisherWithOfficial so skill owners preserve computed official status. |
| convex/skills.public.test.ts | Adds coverage for member-owned publishers being marked official in public skill responses. |
| convex/packages.ts | Uses toPublicPublisherWithOfficial so package owners preserve computed official status. |
| convex/packages.public.test.ts | Adds coverage asserting official owners in public package detail. |
| convex/httpApiV1/packagesV1.ts | Threads owner.official through v1 package/skill detail responses. |
| convex/httpApiV1.handlers.test.ts | Updates handler tests to assert owner.official is emitted in relevant responses. |
| convex/_generated/api.d.ts | Updates generated API typings to include the official publishers lib module. |
Comments suppressed due to low confidence (1)
convex/packages.ts:2164
- This loop now calls
toPublicPublisherWithOfficialfor every package. Because official detection can require extra DB queries for user publishers, this can introduce an N+1 query pattern on the audit page. Consider adding a small cache for the official-org publisher doc and membership checks (similar tomembershipCache) so repeated owners don’t trigger repeated lookups within the same request.
for (const pkg of result.page) {
if (pkg.family === "skill") continue;
if (!(await canViewerReadPackage(ctx, pkg, undefined, membershipCache))) continue;
const owner = await toPublicPublisherWithOfficial(
ctx,
await getOwnerPublisher(ctx, {
ownerPublisherId: pkg.ownerPublisherId,
ownerUserId: pkg.ownerUserId,
}),
);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| owner: { | ||
| _id: Id<"users">; | ||
| handle?: string; | ||
| displayName?: string; | ||
| image?: string; | ||
| official?: boolean; | ||
| } | null; |
| owner: { | ||
| _id: Id<"users">; | ||
| handle?: string; | ||
| displayName?: string; | ||
| image?: string; | ||
| official?: boolean; | ||
| } | null; |
| const ownerPromise = getOwnerPublisher(ctx, { | ||
| ownerPublisherId, | ||
| ownerUserId, | ||
| }).then((ownerDoc) => { | ||
| const publicOwner = toPublicPublisher(ownerDoc); | ||
| }).then(async (ownerDoc) => { | ||
| const publicOwner = await toPublicPublisherWithOfficial(ctx, ownerDoc); | ||
| if (!publicOwner) { |
|
ClawSweeper PR egg 🔥 Warming up: real-behavior proof passed; findings, security review, or rank-up moves are still in progress. Hatch commandComment Hatchability rules:
What is this egg doing here?
|
1d1425c to
0b840fc
Compare
0b840fc to
3a175dd
Compare
3a175dd to
f701e07
Compare
Summary
owner.officialfrom the existing hard-coded OpenClaw policy: theopenclaworg itself and users who are members of that publisher.local-agentic-risk-demois no longer seeded as official and the local seed removes stalelocalmembership in theopenclawpublisher.Intentional Surfaces
The broader coverage is intentional.
buildPublicSkillEntryFromDigestis the shared entry builder for digest-backed list/card surfaces, so addingowner.officialthere keeps the Official badge consistent instead of fixing only one page./$owner/$slugviaskills.getBySlugowner.official./steipete/codex-owner-move-debug-1778257045, where the owner is official even when the skill has no explicitskill.badges.official./skills/skills?sort=...and tag/search filtersowner.official./api/v1/packages/:nameowner.official./plugins/@openclaw/whatsappneeds this field to render the compact owner badge./plugins/$nameowner.officialis true.SkillListItemandSkillCardbrowse resultsskill.badges.officialnow renders Official consistently.localmembership inopenclaw.Before / After Evidence
Screenshots were captured locally from true before/after runs:
origin/mainfunctions +origin/mainfrontend onhttp://127.0.0.1:3010http://127.0.0.1:3011pr-evidence/2407-official-badgesso they render directly in this PR description without adding screenshots to this PR diff./skills?sort=downloadsCodex Owner Move Debug: 0 Official badges.Local Agentic Risk Demo: incorrectly 1 Official badge.Codex Owner Move Debug: 1 Official badge.Local Agentic Risk Demo: 0 Official badges./steipete/codex-owner-move-debug-1778257045/plugins/@openclaw/whatsapp/local/local-agentic-risk-demoValidation
bun run test convex/skills.public.test.ts convex/skills.publicListCursor.test.ts convex/httpApiV1.handlers.test.ts packages/schema/src/schemas.test.ts src/components/SkillListItem.test.tsx src/__tests__/package-detail-route.test.tsxbun run format:checkbun run lintVITE_CONVEX_URL=https://example.invalid bunx tsc --noEmitbunx tsc -p packages/schema/tsconfig.json --noEmitbunx tsc -p packages/clawhub/tsconfig.json --noEmitbunx convex dev --oncebunx convex run devSeed:seedLocalFixtures '{"reset":false}'