Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions convex/lib/public.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,32 @@ describe('public skill mapping', () => {
comments: 0,
})
})

it('returns skill when moderationStatus is active', () => {
const skill = makeSkill({ moderationStatus: 'active' })
expect(toPublicSkill(skill)).not.toBeNull()
})

it('filters out skill when moderationStatus is hidden', () => {
const skill = makeSkill({ moderationStatus: 'hidden' })
expect(toPublicSkill(skill)).toBeNull()
})

it('returns skill when moderationStatus is undefined (legacy)', () => {
const skill = makeSkill({ moderationStatus: undefined as unknown as string })
expect(toPublicSkill(skill)).not.toBeNull()
})

it('filters out soft-deleted skills', () => {
const skill = makeSkill({ softDeletedAt: Date.now() })
expect(toPublicSkill(skill)).toBeNull()
})

it('filters out skills with blocked.malware flag', () => {
const skill = makeSkill({
moderationStatus: 'active',
moderationFlags: ['blocked.malware'],
})
expect(toPublicSkill(skill)).toBeNull()
})
})
32 changes: 31 additions & 1 deletion convex/vt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,21 @@ export const scanWithVirusTotal = internalAction({
handler: async (ctx, args) => {
const apiKey = process.env.VT_API_KEY
if (!apiKey) {
console.log('VT_API_KEY not configured, skipping scan')
console.log('VT_API_KEY not configured, skipping scan — activating skill')
// Activate the skill so it appears in search despite no VT scan.
const version = await ctx.runQuery(internal.skills.getVersionByIdInternal, {
versionId: args.versionId,
})
if (version) {
const skill = await ctx.runQuery(internal.skills.getSkillByIdInternal, {
skillId: version.skillId,
})
if (skill?.moderationReason !== 'quality.low') {
await ctx.runMutation(internal.skills.setSkillModerationStatusActiveInternal, {
skillId: version.skillId,
})
}
}
Comment on lines 308 to 322
Copy link

Choose a reason for hiding this comment

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

same quality gate bypass - check moderationReason before activating

Suggested change
console.log('VT_API_KEY not configured, skipping scan — activating skill')
// Activate the skill so it appears in search despite no VT scan.
const version = await ctx.runQuery(internal.skills.getVersionByIdInternal, {
versionId: args.versionId,
})
if (version) {
await ctx.runMutation(internal.skills.setSkillModerationStatusActiveInternal, {
skillId: version.skillId,
})
}
console.log('VT_API_KEY not configured, skipping scan — activating skill')
// Activate the skill so it appears in search despite no VT scan.
const version = await ctx.runQuery(internal.skills.getVersionByIdInternal, {
versionId: args.versionId,
})
if (version) {
const skill = await ctx.runQuery(internal.skills.getSkillByIdInternal, {
skillId: version.skillId,
})
if (skill?.moderationReason !== 'quality.low') {
await ctx.runMutation(internal.skills.setSkillModerationStatusActiveInternal, {
skillId: version.skillId,
})
}
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/vt.ts
Line: 308:317

Comment:
same quality gate bypass - check `moderationReason` before activating

```suggestion
      console.log('VT_API_KEY not configured, skipping scan — activating skill')
      // Activate the skill so it appears in search despite no VT scan.
      const version = await ctx.runQuery(internal.skills.getVersionByIdInternal, {
        versionId: args.versionId,
      })
      if (version) {
        const skill = await ctx.runQuery(internal.skills.getSkillByIdInternal, {
          skillId: version.skillId,
        })
        if (skill?.moderationReason !== 'quality.low') {
          await ctx.runMutation(internal.skills.setSkillModerationStatusActiveInternal, {
            skillId: version.skillId,
          })
        }
      }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit a8e62e2. Same fix applied — added skill lookup and moderationReason check before activating. This prevents quality gate quarantine bypass in the non-VT-API path.

return
}

Expand Down Expand Up @@ -524,6 +538,14 @@ export const pollPendingScans = internalAction({
versionId,
vtAnalysis: { status: 'stale', checkedAt: Date.now() },
})
// Activate the skill so it appears in search — absence of a VT
// verdict should not permanently hide a published skill.
const skill = await ctx.runQuery(internal.skills.getSkillByIdInternal, { skillId })
if (skill?.moderationReason !== 'quality.low') {
await ctx.runMutation(internal.skills.setSkillModerationStatusActiveInternal, {
skillId,
})
}
staled++
}
continue
Expand All @@ -549,6 +571,14 @@ export const pollPendingScans = internalAction({
versionId,
vtAnalysis: { status: 'stale', checkedAt: Date.now() },
})
// Activate the skill so it appears in search — absence of a VT
// verdict should not permanently hide a published skill.
const skill = await ctx.runQuery(internal.skills.getSkillByIdInternal, { skillId })
if (skill?.moderationReason !== 'quality.low') {
await ctx.runMutation(internal.skills.setSkillModerationStatusActiveInternal, {
skillId,
})
}
staled++
}
continue
Expand Down