convex-components — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited convex-components (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Components are sandboxed packages with their own database tables, functions, and isolated execution.
All components follow the same installation pattern:
npm install @convex-dev/<component-name>// convex/convex.config.ts
import { defineApp } from 'convex/server';
import componentName from '@convex-dev/<component-name>/convex.config';
const app = defineApp();
app.use(componentName);
// Multiple instances with different names
app.use(componentName, { name: 'instance2' });
export default app;Run npx convex dev to generate code.
import { components } from './_generated/api';
// Default instance
const instance = new ComponentClass(components.componentName, {
/* config */
});
// Named instance
const instance2 = new ComponentClass(components.instance2, {
/* config */
});Component mutations participate in the parent transaction:
export const doWork = mutation({
handler: async (ctx) => {
await ctx.db.insert('myTable', { data: 'value' });
await component.doSomething(ctx); // Same transaction
// If mutation throws, BOTH writes roll back
}
});Component exceptions can be caught:
try {
await rateLimiter.limit(ctx, 'myLimit', { throws: true });
} catch (e) {
// Only component's writes roll back
// Parent mutation can continue
}| Component | Package | Primary Use |
|---|---|---|
| Rate Limiter | @convex-dev/rate-limiter | Control action frequency |
| Aggregate | @convex-dev/aggregate | Fast count/sum queries |
| Sharded Counter | @convex-dev/sharded-counter | High-throughput counting |
| Presence | @convex-dev/presence | Real-time user tracking |
| Action Cache | @convex-dev/action-cache | Cache expensive results |
| Migrations | @convex-dev/migrations | Online data migrations |
| Workpool | @convex-dev/workpool | Queue work with limits |
| Workflow | @convex-dev/workflow | Durable multi-step flows |
| Action Retrier | @convex-dev/action-retrier | Retry failed actions |
| ProseMirror Sync | @convex-dev/prosemirror-sync | Collaborative text editing |
| Resend | @convex-dev/resend | Transactional email |
| Stripe | @convex-dev/stripe | Payments & subscriptions |
| Agent | @convex-dev/agent | AI chat with history |
Auto-sync components with table changes using convex-helpers triggers:
import { Triggers } from 'convex-helpers/server/triggers';
import {
customCtx,
customMutation
} from 'convex-helpers/server/customFunctions';
const triggers = new Triggers<DataModel>();
// Register component trigger
triggers.register('myTable', aggregate.trigger());
// Wrap mutation to use triggers
const mutation = customMutation(mutationRaw, customCtx(triggers.wrapDB));import componentTest from '@convex-dev/<component>/test';
import { convexTest } from 'convex-test';
function initTest() {
const t = convexTest();
componentTest.register(t);
return t;
}
test('component test', async () => {
const t = initTest();
await t.run(async (ctx) => {
// Test with component
});
});View component data in dashboard via component dropdown. Each component has isolated tables.
emailWorkpool, scrapeWorkpool vs generic workpool1~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.