Use this skill when contributing to InsForge's backend package. This is for maintainers editing backend routes, services, providers, auth, database logic (including RLS-enforced surfaces like storage and realtime), schedules, or backend tests in the InsForge monorepo.
73
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Use this skill for backend/ work in the InsForge repository.
backend/src/api/**backend/src/services/**backend/src/providers/**backend/src/infra/**backend/tests/**Keep the route -> service -> provider/infra split intact.
Follow backend conventions.
.js import specifiers in TypeScript source.@insforge/shared-schemas when contracts cross packages.safeParse plus AppError for invalid input.successResponse.verifyAdmin, verifyUser, and verifyApiKey.any type. Prefer precise interfaces, schema-derived types, unknown, or constrained generics.backend/src/infra/database/migrations/.Write idempotent migrations. Every SQL migration must be safe to re-run.
CREATE TABLE IF NOT EXISTS, CREATE INDEX IF NOT EXISTS, ADD COLUMN IF NOT EXISTS.ALTER TABLE ... RENAME TO — it fails if the target name already exists. Wrap renames in a DO block that checks information_schema.tables for both source and target.DROP TRIGGER IF EXISTS before CREATE TRIGGER.DROP COLUMN behind information_schema.columns checks when the column may already be gone.ON CONFLICT or WHERE NOT EXISTS for seed INSERT statements.Preserve existing behavior around mutation flows.
Use Postgres Row Level Security, not app-side filters, for tables accessed via authenticated end-user routes (anything where req.user reaches the service layer). RLS-enforced services such as storage, realtime, and payments should use withUserContext. Tables accessed only by admin or service-internal paths (audit logs, billing aggregations) don't need RLS. Do not write WHERE user_id = $1 filters in services; let RLS evaluate auth.jwt() ->> 'sub' against the row.
withUserContext(pool, ctx, fn, settings?) from services/database/user-context.service.ts. It opens a transaction, sets SET LOCAL ROLE plus the canonical request.jwt.claims JSON GUC via set_config, applies optional transaction-local settings such as realtime.channel_name, runs fn, commits on success or rolls back on error, and resets role in finally so policies see the calling user via auth.jwt() ->> 'sub'.UserContext user-only and defined in api/middlewares/auth.ts: { id, role, email? } (id is always present at the API level). API keys and admin bypass flags do not belong inside UserContext.StorageService.objectIsVisible as the template.IF EXISTS (SELECT 1 FROM <table>) THEN <create policies> END IF pattern.GRANT table-level CRUD to authenticated, and write per-operation policies (SELECT, INSERT, UPDATE, DELETE). Public-bucket-style anonymous bypasses live at the route layer before calling the RLS helper, not in policies.project_admin. It has service-key row visibility, but PostgreSQL grants and ownership still limit object access and DDL.Always write unit tests for new code.
tests/unit/redirect-url-whitelist-migration.test.ts for the pattern).tests/unit/user-context.service.test.ts and tests/unit/storage-object-is-visible.test.ts).cd backend && npm test.cd backend && npm testcd backend && npm run buildFor contract changes, also validate packages/shared-schemas/ and any affected dashboard consumers.
9cf009b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.