Skip to main content

controllers

Rails controllers, routes, strong params and responses, with tenant scoping and authorization on every action. Use when adding or changing an endpoint, a route, or an action's params, authorization or response.

Source facts

Repository
zoolutions/claude-plugins
Last source activity
October 17, 2026 at 18:59
Detected SKILL.md language
English
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
controllers
description
Rails controllers, routes, strong params and responses, with tenant scoping and authorization on every action. Use when adding or changing an endpoint, a route, or an action's params, authorization or response.
argument-hint
controller, route or action task
allowed-tools
Bash(*), Read, Write, Edit, Glob, Grep, Skill
model
sonnet
# Controllers: $ARGUMENTS **Read the repository first.** `AGENTS.md` → `## Workflow`: **Tenant**, **Authorization**, **Views**, **Interactivity**, **Specs**. A missing label means "none". ## Every action, in order 1. **Authenticate.** The base controller's `before_action` stays on. Skipping it needs a comment saying why the endpoint is public. 2. **Load through the tenant root** (Workflow → Tenant): `current_tenant.things.find(params[:id])`. Never `Thing.find(params[:id])`: it lets a user of one tenant read another's record. 3. **Authorize** with the library in Workflow → Authorization: member actions on the record, `index` on the scoped collection, `new`/`create` on the built record. Compare actions: if `index` scopes, `show`, `update` and `destroy` must scope the same way. 4. **Strong params.** Explicit `permit(...)`, never `permit!`. Never permit the tenant FK, owner, role, status, balance or any flag the user may not set; set those server-side. 5. **Delegate.** More than a few lines of business logic → a service (/rails-app:services); the action calls it and branches on its result. 6. **Render** per Workflow → Views. Phlex: `render Views::Things::Show.new(thing:)` with keyword args; never instance variables leaking into the view, never `render "things/show"`. When Workflow → Views names a native-view resolver, wrap the class with it. 7. **Background** anything slow (HTTP calls, mail, file processing, more than ~500 ms) as a job with IDs (/rails-app:jobs). ## Responses - Failed create/update: re-render with `status: :unprocessable_entity` (Turbo ignores a 200 form response). Successful write: redirect; after `destroy`, `redirect_to …, status: :see_other`. - Partial updates follow Workflow → Interactivity. With phlex-reactive the component's `action` answers (`reply.morph`), not a new `respond_to … format.turbo_stream`; existing Turbo Stream code is maintained, not extended (/rails-app:stimulus). - JSON: an explicit serializer or `as_json(only: …)`; `render json: record` leaks every column. - Errors: no `rescue => e` that renders `e.message` to the user. ## Routes - `resources … only:`. A custom verb becomes a nested resource (`Things::ArchivesController#create`) rather than a member action, when it has its own authorization rule. - A catch-all route goes last and must not shadow engine routes (e.g. `POST /reactive/actions`, health checks). Run `bin/rails routes -g <name>` after editing. - Webhook endpoints verify the signature before reading the payload (/rails-app:security). ## Never | Wrong | Right | |---|---| | `Thing.find(params[:id])` | `current_tenant.things.find(params[:id])` | | an action without an authorization call | the library's call per Workflow → Authorization | | `params.permit!` / permitting `role`, `*_id` of the tenant | explicit `permit` of user-editable fields | | `render "things/show"`, ivars into a Phlex view | `render Views::Things::Show.new(thing:)` | | 40 lines of logic in `create` | a service object | ## Spec Request specs (/rails-app:tests) for what a browser flow does not prove: each role allowed and denied, a record of another tenant answers 404, a forbidden param is ignored. The happy path belongs in the feature's system spec. Done when the spec is green and Workflow → Verify passes.
View on GitHub