ima-claude 2.20.0 → 2.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -9
- package/dist/cli.js +2 -1
- package/package.json +1 -1
- package/plugins/ima-claude/.claude-plugin/plugin.json +2 -2
- package/plugins/ima-claude/agents/explorer.md +29 -15
- package/plugins/ima-claude/agents/implementer.md +58 -13
- package/plugins/ima-claude/agents/memory.md +19 -19
- package/plugins/ima-claude/agents/reviewer.md +84 -34
- package/plugins/ima-claude/agents/tester.md +59 -16
- package/plugins/ima-claude/agents/wp-developer.md +66 -21
- package/plugins/ima-claude/hooks/bootstrap.sh +42 -44
- package/plugins/ima-claude/hooks/prompt_coach_digest.md +14 -17
- package/plugins/ima-claude/hooks/prompt_coach_system.md +10 -12
- package/plugins/ima-claude/personalities/README.md +17 -6
- package/plugins/ima-claude/personalities/enable-efficient.md +61 -0
- package/plugins/ima-claude/personalities/enable-terse.md +71 -0
- package/plugins/ima-claude/skills/agentic-workflows/SKILL.md +35 -71
- package/plugins/ima-claude/skills/architect/SKILL.md +54 -168
- package/plugins/ima-claude/skills/compound-bridge/SKILL.md +41 -94
- package/plugins/ima-claude/skills/design-to-code/SKILL.md +43 -78
- package/plugins/ima-claude/skills/discourse/SKILL.md +79 -194
- package/plugins/ima-claude/skills/discourse-admin/SKILL.md +41 -103
- package/plugins/ima-claude/skills/docs-organize/SKILL.md +63 -203
- package/plugins/ima-claude/skills/ember-discourse/SKILL.md +90 -200
- package/plugins/ima-claude/skills/espocrm/SKILL.md +14 -23
- package/plugins/ima-claude/skills/espocrm-api/SKILL.md +79 -192
- package/plugins/ima-claude/skills/functional-programmer/SKILL.md +33 -237
- package/plugins/ima-claude/skills/gh-cli/SKILL.md +26 -65
- package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +71 -104
- package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +32 -22
- package/plugins/ima-claude/skills/ima-brand/SKILL.md +18 -23
- package/plugins/ima-claude/skills/ima-copywriting/SKILL.md +68 -179
- package/plugins/ima-claude/skills/ima-doc2pdf/SKILL.md +32 -102
- package/plugins/ima-claude/skills/ima-editorial-scorecard/SKILL.md +38 -63
- package/plugins/ima-claude/skills/ima-editorial-workflow/SKILL.md +69 -114
- package/plugins/ima-claude/skills/ima-email-creator/SKILL.md +16 -22
- package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +21 -37
- package/plugins/ima-claude/skills/ima-git/SKILL.md +81 -0
- package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +39 -120
- package/plugins/ima-claude/skills/jquery/SKILL.md +107 -233
- package/plugins/ima-claude/skills/js-fp/SKILL.md +75 -296
- package/plugins/ima-claude/skills/js-fp-api/SKILL.md +52 -162
- package/plugins/ima-claude/skills/js-fp-react/SKILL.md +47 -270
- package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +55 -209
- package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +59 -204
- package/plugins/ima-claude/skills/livecanvas/SKILL.md +19 -32
- package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +92 -162
- package/plugins/ima-claude/skills/mcp-context7/SKILL.md +32 -64
- package/plugins/ima-claude/skills/mcp-gitea/SKILL.md +98 -188
- package/plugins/ima-claude/skills/mcp-github/SKILL.md +60 -124
- package/plugins/ima-claude/skills/mcp-memory/SKILL.md +1 -177
- package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +58 -115
- package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +32 -87
- package/plugins/ima-claude/skills/mcp-serena/SKILL.md +54 -80
- package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +40 -63
- package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +75 -116
- package/plugins/ima-claude/skills/php-authnet/SKILL.md +32 -65
- package/plugins/ima-claude/skills/php-fp/SKILL.md +50 -129
- package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +25 -73
- package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +103 -463
- package/plugins/ima-claude/skills/playwright/SKILL.md +69 -220
- package/plugins/ima-claude/skills/prompt-starter/SKILL.md +33 -83
- package/plugins/ima-claude/skills/prompt-starter/references/code-review.md +38 -0
- package/plugins/ima-claude/skills/py-fp/SKILL.md +78 -384
- package/plugins/ima-claude/skills/quasar-fp/SKILL.md +54 -255
- package/plugins/ima-claude/skills/quickstart/SKILL.md +7 -11
- package/plugins/ima-claude/skills/rails/SKILL.md +63 -184
- package/plugins/ima-claude/skills/resume-session/SKILL.md +14 -35
- package/plugins/ima-claude/skills/rg/SKILL.md +61 -146
- package/plugins/ima-claude/skills/ruby-fp/SKILL.md +66 -163
- package/plugins/ima-claude/skills/save-session/SKILL.md +10 -39
- package/plugins/ima-claude/skills/scorecard/SKILL.md +42 -40
- package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +42 -71
- package/plugins/ima-claude/skills/skill-creator/SKILL.md +79 -250
- package/plugins/ima-claude/skills/task-master/SKILL.md +11 -31
- package/plugins/ima-claude/skills/task-planner/SKILL.md +44 -153
- package/plugins/ima-claude/skills/task-runner/SKILL.md +61 -143
- package/plugins/ima-claude/skills/unit-testing/SKILL.md +59 -134
- package/plugins/ima-claude/skills/wp-ddev/SKILL.md +38 -120
- package/plugins/ima-claude/skills/wp-local/SKILL.md +26 -108
|
@@ -5,38 +5,19 @@ description: "Ruby on Rails conventions + security - strong parameters, ActiveRe
|
|
|
5
5
|
|
|
6
6
|
# Rails
|
|
7
7
|
|
|
8
|
-
Convention-over-configuration
|
|
8
|
+
Convention-over-configuration on the happy path. Work with Rails opinions, not against them.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**Foundation**: Reference `../ruby-fp/SKILL.md` for Ruby FP core. Business logic in service objects — keep models and controllers thin.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- Reviewing Rails code for security or structure
|
|
14
|
-
- Adding features to an existing Rails application
|
|
15
|
-
- Discourse plugin development (see also `discourse` skill)
|
|
16
|
-
|
|
17
|
-
## Core Philosophy
|
|
18
|
-
|
|
19
|
-
Rails has opinions. Work with them, not against them. The framework gives you:
|
|
20
|
-
- SQL injection protection via ActiveRecord (use it)
|
|
21
|
-
- CSRF protection by default (don't disable it)
|
|
22
|
-
- XSS protection via ERB auto-escaping (use `<%= %>`)
|
|
23
|
-
- Mass assignment protection via Strong Parameters (permit explicitly)
|
|
24
|
-
|
|
25
|
-
**Functional core still applies in Rails.** Business logic in service modules/plain Ruby objects. Keep models and controllers thin.
|
|
26
|
-
|
|
27
|
-
**Foundation**: Reference `../ruby-fp/SKILL.md` for Ruby FP core principles.
|
|
28
|
-
|
|
29
|
-
## The 5 Non-Negotiable Security Practices
|
|
12
|
+
## 5 Non-Negotiable Security Practices
|
|
30
13
|
|
|
31
14
|
| Practice | Prevents | Rule |
|
|
32
15
|
|----------|----------|------|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
39
|
-
### Quick Reference: The Five in Code
|
|
16
|
+
| Strong Parameters | Mass assignment | `params.require(:model).permit(:field, ...)` on ALL controller actions |
|
|
17
|
+
| Parameterized Queries | SQL injection | ActiveRecord methods or `?`/named placeholders — NEVER string interpolation |
|
|
18
|
+
| CSRF Protection | CSRF | Never disable `protect_from_forgery`; use `form_with` helpers |
|
|
19
|
+
| Before Actions (Auth) | Unauthorized access | `before_action :authenticate_user!` on ALL sensitive actions |
|
|
20
|
+
| Secrets via Credentials | Credential exposure | Rails credentials or `ENV.fetch` — never hardcode |
|
|
40
21
|
|
|
41
22
|
```ruby
|
|
42
23
|
# 1. Strong Parameters
|
|
@@ -45,21 +26,19 @@ def user_params
|
|
|
45
26
|
# Never: params[:user] or params.permit!
|
|
46
27
|
end
|
|
47
28
|
|
|
48
|
-
# 2. Parameterized Queries
|
|
29
|
+
# 2. Parameterized Queries
|
|
49
30
|
User.where(email: params[:email]) # safe
|
|
50
31
|
User.where("email = ?", params[:email]) # safe
|
|
51
|
-
User.where("email = :email", email: params[:email]) # safe
|
|
52
32
|
User.where("email = '#{params[:email]}'") # NEVER — SQL injection
|
|
53
33
|
|
|
54
|
-
# 3. CSRF — keep default
|
|
34
|
+
# 3. CSRF — keep default
|
|
55
35
|
class ApplicationController < ActionController::Base
|
|
56
36
|
protect_from_forgery with: :exception # default — keep it
|
|
57
37
|
end
|
|
58
|
-
# form_with and form_for automatically include the token
|
|
59
38
|
|
|
60
39
|
# 4. Before action auth
|
|
61
40
|
class PostsController < ApplicationController
|
|
62
|
-
before_action :authenticate_user!
|
|
41
|
+
before_action :authenticate_user!
|
|
63
42
|
before_action :require_admin, only: [:destroy]
|
|
64
43
|
|
|
65
44
|
private
|
|
@@ -68,133 +47,83 @@ class PostsController < ApplicationController
|
|
|
68
47
|
end
|
|
69
48
|
end
|
|
70
49
|
|
|
71
|
-
# 5. Credentials
|
|
72
|
-
|
|
73
|
-
#
|
|
74
|
-
# ENV fallback: ENV.fetch('STRIPE_SECRET_KEY')
|
|
50
|
+
# 5. Credentials
|
|
51
|
+
Rails.application.credentials.stripe[:secret_key]
|
|
52
|
+
ENV.fetch('STRIPE_SECRET_KEY') # raises KeyError if missing
|
|
75
53
|
```
|
|
76
54
|
|
|
77
55
|
## ActiveRecord Safety
|
|
78
56
|
|
|
79
57
|
```ruby
|
|
80
|
-
# SAFE
|
|
81
|
-
User.find(params[:id])
|
|
58
|
+
# SAFE
|
|
59
|
+
User.find(params[:id])
|
|
82
60
|
User.find_by(email: params[:email])
|
|
83
61
|
User.where(status: params[:status])
|
|
84
62
|
User.where("created_at > ?", 1.week.ago)
|
|
85
|
-
|
|
86
|
-
# SAFE — sanitize_sql_like for LIKE patterns
|
|
87
63
|
query = ActiveRecord::Base.sanitize_sql_like(params[:search])
|
|
88
64
|
User.where("name LIKE ?", "%#{query}%")
|
|
89
65
|
|
|
90
|
-
# UNSAFE — never
|
|
91
|
-
User.where("id = #{params[:id]}")
|
|
92
|
-
User.where("name LIKE '%#{params[:q]}%'")
|
|
93
|
-
User.find_by("email = '#{email}'")
|
|
66
|
+
# UNSAFE — never
|
|
67
|
+
User.where("id = #{params[:id]}")
|
|
68
|
+
User.where("name LIKE '%#{params[:q]}%'")
|
|
69
|
+
User.find_by("email = '#{email}'")
|
|
94
70
|
|
|
95
|
-
# Raw SQL
|
|
71
|
+
# Raw SQL — use bind params
|
|
96
72
|
User.find_by_sql(["SELECT * FROM users WHERE token = ?", token])
|
|
97
|
-
ActiveRecord::Base.connection.execute(
|
|
98
|
-
ActiveRecord::Base.sanitize_sql(["UPDATE users SET x = ? WHERE id = ?", val, id])
|
|
99
|
-
)
|
|
100
73
|
```
|
|
101
74
|
|
|
102
75
|
## Mass Assignment
|
|
103
76
|
|
|
104
77
|
```ruby
|
|
105
|
-
# BAD
|
|
106
|
-
User.new(params[:user])
|
|
107
|
-
User.update(params.permit!)
|
|
78
|
+
# BAD
|
|
79
|
+
User.new(params[:user])
|
|
80
|
+
User.update(params.permit!)
|
|
108
81
|
|
|
109
|
-
# GOOD
|
|
82
|
+
# GOOD
|
|
110
83
|
def user_params
|
|
111
84
|
params.require(:user).permit(:name, :email, :bio)
|
|
112
85
|
end
|
|
113
|
-
|
|
114
|
-
# Nested params
|
|
115
86
|
def post_params
|
|
116
87
|
params.require(:post).permit(:title, :body, tags: [], author: [:name, :email])
|
|
117
88
|
end
|
|
118
89
|
|
|
119
|
-
#
|
|
120
|
-
# role, admin, password_digest, confirmed_at — set these explicitly in code
|
|
90
|
+
# Set sensitive fields explicitly — never from params
|
|
121
91
|
def promote_to_admin
|
|
122
|
-
@user.update!(role: 'admin')
|
|
92
|
+
@user.update!(role: 'admin')
|
|
123
93
|
end
|
|
124
94
|
```
|
|
125
95
|
|
|
126
96
|
## XSS in Views
|
|
127
97
|
|
|
128
98
|
```ruby
|
|
129
|
-
# ERB auto-escaping — always use <%= %> for user content
|
|
130
99
|
<%= user.name %> # safe — HTML-escaped
|
|
131
|
-
<%== user.name %> # UNSAFE — raw output
|
|
132
|
-
<%= raw user.name %> # UNSAFE
|
|
133
|
-
<%= user.name.html_safe %> # UNSAFE — marking untrusted content safe
|
|
134
|
-
|
|
135
|
-
# When you need to render HTML you control
|
|
100
|
+
<%== user.name %> # UNSAFE — raw output
|
|
101
|
+
<%= raw user.name %> # UNSAFE
|
|
136
102
|
<%= sanitize user.bio, tags: %w[b i em strong p] %>
|
|
137
103
|
|
|
138
|
-
#
|
|
139
|
-
<script>var name = "<%= user.name %>"</script> # UNSAFE — XSS via JS
|
|
140
|
-
# GOOD
|
|
141
|
-
<script>var data = <%= user.to_json.html_safe %></script> # if you control the data
|
|
142
|
-
# BEST — pass via data attributes
|
|
104
|
+
# JS context — pass via data attributes, not interpolation
|
|
143
105
|
<div data-user-name="<%= user.name %>"></div>
|
|
144
106
|
```
|
|
145
107
|
|
|
146
|
-
## Authentication & Authorization
|
|
108
|
+
## Authentication & Authorization
|
|
147
109
|
|
|
148
110
|
```ruby
|
|
149
|
-
# Authentication — Devise is the Rails default
|
|
150
|
-
# Before action guards all sensitive routes
|
|
151
111
|
class ApplicationController < ActionController::Base
|
|
152
112
|
before_action :authenticate_user!
|
|
153
|
-
|
|
154
|
-
# Override to allow public actions
|
|
155
113
|
skip_before_action :authenticate_user!, only: [:index, :show]
|
|
156
114
|
end
|
|
157
115
|
|
|
158
|
-
#
|
|
116
|
+
# Policy object (Pundit pattern)
|
|
159
117
|
class PostPolicy
|
|
160
|
-
def initialize(user, post)
|
|
161
|
-
|
|
162
|
-
@post = post
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def update?
|
|
166
|
-
@user.admin? || @post.user_id == @user.id
|
|
167
|
-
end
|
|
118
|
+
def initialize(user, post) = @user, @post = user, post
|
|
119
|
+
def update? = @user.admin? || @post.user_id == @user.id
|
|
168
120
|
end
|
|
169
121
|
|
|
170
|
-
# In controller
|
|
171
122
|
def update
|
|
172
123
|
@post = Post.find(params[:id])
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
# ... update logic
|
|
124
|
+
return head :forbidden unless PostPolicy.new(current_user, @post).update?
|
|
125
|
+
# update logic
|
|
176
126
|
end
|
|
177
|
-
|
|
178
|
-
# NEVER rely on hidden fields or client-side checks alone
|
|
179
|
-
# Always enforce auth server-side
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Secrets Management
|
|
183
|
-
|
|
184
|
-
```ruby
|
|
185
|
-
# config/credentials.yml.enc (encrypted, safe to commit)
|
|
186
|
-
# Edit with: rails credentials:edit
|
|
187
|
-
# Access:
|
|
188
|
-
Rails.application.credentials.database[:password]
|
|
189
|
-
Rails.application.credentials.dig(:aws, :access_key_id)
|
|
190
|
-
|
|
191
|
-
# ENV for 12-factor apps (Heroku, Docker, etc.)
|
|
192
|
-
# Always use fetch to fail loudly if missing
|
|
193
|
-
DB_PASSWORD = ENV.fetch('DB_PASSWORD') # raises KeyError if missing
|
|
194
|
-
DB_PASSWORD = ENV.fetch('DB_PASSWORD') { raise "DB_PASSWORD not set" }
|
|
195
|
-
|
|
196
|
-
# Never in source code
|
|
197
|
-
config.secret_key_base = "abc123hardcoded" # NEVER
|
|
198
127
|
```
|
|
199
128
|
|
|
200
129
|
## Controller Pattern
|
|
@@ -205,9 +134,7 @@ class UsersController < ApplicationController
|
|
|
205
134
|
before_action :set_user, only: [:show, :update, :destroy]
|
|
206
135
|
before_action :authorize_user!, only: [:update, :destroy]
|
|
207
136
|
|
|
208
|
-
def show
|
|
209
|
-
render json: @user.as_json(only: [:id, :name, :email])
|
|
210
|
-
end
|
|
137
|
+
def show = render json: @user.as_json(only: [:id, :name, :email])
|
|
211
138
|
|
|
212
139
|
def update
|
|
213
140
|
if @user.update(user_params)
|
|
@@ -219,71 +146,46 @@ class UsersController < ApplicationController
|
|
|
219
146
|
|
|
220
147
|
private
|
|
221
148
|
|
|
222
|
-
def set_user
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
def authorize_user!
|
|
227
|
-
head :forbidden unless current_user.admin? || @user == current_user
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def user_params
|
|
231
|
-
params.require(:user).permit(:name, :email, :bio)
|
|
232
|
-
end
|
|
149
|
+
def set_user = @user = User.find(params[:id])
|
|
150
|
+
def authorize_user! = head :forbidden unless current_user.admin? || @user == current_user
|
|
151
|
+
def user_params = params.require(:user).permit(:name, :email, :bio)
|
|
233
152
|
end
|
|
234
153
|
```
|
|
235
154
|
|
|
236
|
-
## Model: Thin, Validated
|
|
155
|
+
## Model: Thin, Validated
|
|
237
156
|
|
|
238
157
|
```ruby
|
|
239
158
|
class User < ApplicationRecord
|
|
240
|
-
# Validations
|
|
241
159
|
validates :email, presence: true, uniqueness: { case_sensitive: false },
|
|
242
160
|
format: { with: URI::MailTo::EMAIL_REGEXP }
|
|
243
161
|
validates :name, presence: true, length: { maximum: 100 }
|
|
244
162
|
|
|
245
|
-
# Scopes — declarative query building
|
|
246
163
|
scope :active, -> { where(active: true) }
|
|
247
164
|
scope :recent, -> { order(created_at: :desc) }
|
|
248
|
-
scope :admins, -> { where(role: 'admin') }
|
|
249
165
|
|
|
250
|
-
# Callbacks — use sparingly, only for model lifecycle concerns
|
|
251
166
|
before_save :normalize_email
|
|
252
|
-
|
|
253
|
-
# Associations
|
|
254
167
|
has_many :posts, dependent: :destroy
|
|
255
|
-
belongs_to :organization
|
|
256
168
|
|
|
257
169
|
private
|
|
258
|
-
|
|
259
|
-
def normalize_email
|
|
260
|
-
self.email = email.to_s.strip.downcase
|
|
261
|
-
end
|
|
170
|
+
def normalize_email = self.email = email.to_s.strip.downcase
|
|
262
171
|
end
|
|
263
|
-
|
|
264
|
-
# Business logic lives in service objects, NOT the model
|
|
265
|
-
# UserRegistrationService, UserImportService, etc.
|
|
172
|
+
# Business logic → service objects
|
|
266
173
|
```
|
|
267
174
|
|
|
268
|
-
## Service Objects (Functional Core
|
|
175
|
+
## Service Objects (Functional Core)
|
|
269
176
|
|
|
270
177
|
```ruby
|
|
271
|
-
# app/services/user_registration_service.rb
|
|
272
178
|
class UserRegistrationService
|
|
273
179
|
Result = Data.define(:success, :user, :errors)
|
|
274
180
|
|
|
275
|
-
def self.call(attrs)
|
|
276
|
-
new(attrs).call
|
|
277
|
-
end
|
|
181
|
+
def self.call(attrs) = new(attrs).call
|
|
278
182
|
|
|
279
|
-
def initialize(attrs)
|
|
280
|
-
@attrs = attrs
|
|
281
|
-
end
|
|
183
|
+
def initialize(attrs) = @attrs = attrs
|
|
282
184
|
|
|
283
185
|
def call
|
|
284
186
|
user = User.new(normalized_attrs)
|
|
285
187
|
if user.save
|
|
286
|
-
|
|
188
|
+
WelcomeMailer.with(user: user).welcome_email.deliver_later
|
|
287
189
|
Result.new(success: true, user: user, errors: [])
|
|
288
190
|
else
|
|
289
191
|
Result.new(success: false, user: nil, errors: user.errors.full_messages)
|
|
@@ -298,13 +200,8 @@ class UserRegistrationService
|
|
|
298
200
|
name: @attrs[:name].to_s.strip
|
|
299
201
|
)
|
|
300
202
|
end
|
|
301
|
-
|
|
302
|
-
def send_welcome_email(user)
|
|
303
|
-
WelcomeMailer.with(user: user).welcome_email.deliver_later
|
|
304
|
-
end
|
|
305
203
|
end
|
|
306
204
|
|
|
307
|
-
# Usage in controller
|
|
308
205
|
result = UserRegistrationService.call(user_params)
|
|
309
206
|
```
|
|
310
207
|
|
|
@@ -312,18 +209,13 @@ result = UserRegistrationService.call(user_params)
|
|
|
312
209
|
|
|
313
210
|
```
|
|
314
211
|
app/
|
|
315
|
-
├── controllers/
|
|
316
|
-
|
|
317
|
-
├──
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
│ └── user_registration_service.rb # Business logic
|
|
321
|
-
├── policies/
|
|
322
|
-
│ └── user_policy.rb # Authorization rules
|
|
323
|
-
└── views/
|
|
324
|
-
└── users/ # Only <%= %> — never <%== %>
|
|
212
|
+
├── controllers/ # Thin — delegate to services
|
|
213
|
+
├── models/ # Validations, scopes, associations only
|
|
214
|
+
├── services/ # Business logic
|
|
215
|
+
├── policies/ # Authorization rules
|
|
216
|
+
└── views/ # Only <%= %> — never <%== %>
|
|
325
217
|
config/
|
|
326
|
-
└── credentials.yml.enc
|
|
218
|
+
└── credentials.yml.enc # Secrets (encrypted)
|
|
327
219
|
```
|
|
328
220
|
|
|
329
221
|
## Security Checklist
|
|
@@ -331,29 +223,16 @@ config/
|
|
|
331
223
|
- [ ] Strong Parameters on all mutating actions
|
|
332
224
|
- [ ] No string interpolation in SQL queries
|
|
333
225
|
- [ ] `protect_from_forgery` enabled (default — don't remove)
|
|
334
|
-
- [ ] `before_action` auth
|
|
335
|
-
- [ ] No secrets in source
|
|
226
|
+
- [ ] `before_action` auth on all sensitive routes
|
|
227
|
+
- [ ] No secrets in source — credentials or `ENV.fetch`
|
|
336
228
|
- [ ] ERB uses `<%= %>` not `<%== %>` for user content
|
|
337
|
-
- [ ] `sanitize`
|
|
338
|
-
- [ ]
|
|
229
|
+
- [ ] `sanitize` for user-supplied HTML
|
|
230
|
+
- [ ] `bundle exec bundler-audit check --update`
|
|
339
231
|
|
|
340
|
-
##
|
|
341
|
-
|
|
342
|
-
### Security Deep Dive
|
|
343
|
-
**File**: [`references/security.md`](references/security.md)
|
|
344
|
-
**Load when**: Need vulnerable vs. safe comparisons, injection examples, CSRF details
|
|
345
|
-
**Contains**: Full attack examples, all Rails security helpers, CSP configuration
|
|
346
|
-
|
|
347
|
-
### ActiveRecord Patterns
|
|
348
|
-
**File**: [`references/activerecord.md`](references/activerecord.md)
|
|
349
|
-
**Load when**: Complex queries, raw SQL needs, migration patterns, performance
|
|
350
|
-
**Contains**: Query interface, raw SQL safety, N+1 prevention, index strategy
|
|
351
|
-
|
|
352
|
-
### Testing Strategy
|
|
353
|
-
**File**: [`references/testing.md`](references/testing.md)
|
|
354
|
-
**Load when**: Writing request specs, model specs, service object tests
|
|
355
|
-
**Contains**: RSpec patterns, factory patterns, security test examples
|
|
356
|
-
|
|
357
|
-
---
|
|
232
|
+
## Reference Files
|
|
358
233
|
|
|
359
|
-
|
|
234
|
+
| File | Load when |
|
|
235
|
+
|------|-----------|
|
|
236
|
+
| [`references/security.md`](references/security.md) | Vulnerable vs. safe comparisons, injection examples, CSP |
|
|
237
|
+
| [`references/activerecord.md`](references/activerecord.md) | Complex queries, raw SQL, migrations, N+1 prevention |
|
|
238
|
+
| [`references/testing.md`](references/testing.md) | RSpec patterns, factory patterns, security tests |
|
|
@@ -5,64 +5,43 @@ description: "Resume previous session from Serena MCP memory. Use when: resume s
|
|
|
5
5
|
|
|
6
6
|
# resume-session
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Steps
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- "load session"
|
|
15
|
-
- "continue session"
|
|
16
|
-
- "resume from save"
|
|
17
|
-
|
|
18
|
-
## Instructions
|
|
19
|
-
|
|
20
|
-
1. Use `mcp__serena__read_memory` with memory name `session-state`
|
|
21
|
-
2. Search Vestige for project context: `mcp__vestige__search query: "{project-name}" limit: 5`
|
|
22
|
-
3. Check for pending intentions: `mcp__vestige__intention action: "check"`
|
|
23
|
-
4. Parse the content and provide a brief status summary
|
|
24
|
-
5. Wait for user direction before taking action
|
|
10
|
+
1. `mcp__serena__read_memory` with name `session-state`
|
|
11
|
+
2. `mcp__vestige__search query: "{project-name}" limit: 5`
|
|
12
|
+
3. `mcp__vestige__intention action: "check"`
|
|
13
|
+
4. Summarize state, wait for user direction
|
|
25
14
|
|
|
26
15
|
## Output Format
|
|
27
16
|
|
|
28
17
|
```
|
|
29
18
|
## Session Resumed
|
|
30
19
|
|
|
31
|
-
**Task**: {current task
|
|
32
|
-
**Last saved**: {date
|
|
20
|
+
**Task**: {current task}
|
|
21
|
+
**Last saved**: {date}
|
|
33
22
|
|
|
34
23
|
### Status
|
|
35
|
-
- {
|
|
36
|
-
- {
|
|
37
|
-
- {
|
|
24
|
+
- {what was in progress}
|
|
25
|
+
- {key decision or context}
|
|
26
|
+
- {main outstanding item}
|
|
38
27
|
|
|
39
28
|
### Suggested Next Step
|
|
40
|
-
{
|
|
29
|
+
{Resume Hint from memory, or first outstanding item}
|
|
41
30
|
|
|
42
31
|
Ready to continue. What would you like to focus on?
|
|
43
32
|
```
|
|
44
33
|
|
|
45
34
|
## Rules
|
|
46
35
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
- **Do not** re-read files mentioned unless user asks
|
|
50
|
-
- **Do** present the state clearly and wait for direction
|
|
36
|
+
- Read and summarize only — no automatic action on outstanding items
|
|
37
|
+
- Do not re-read files unless asked
|
|
51
38
|
|
|
52
39
|
## If Memory Not Found
|
|
53
40
|
|
|
54
|
-
Respond with:
|
|
55
41
|
```
|
|
56
42
|
No session memory found.
|
|
57
43
|
|
|
58
44
|
To save a session, use: /ima-claude:save-session
|
|
59
45
|
```
|
|
60
46
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## Technical Notes
|
|
64
|
-
|
|
65
|
-
- Uses Serena MCP `read_memory` tool (no file path confusion)
|
|
66
|
-
- Memory persists across Claude sessions in project context
|
|
67
|
-
- Project-specific storage (sessions are project-bound)
|
|
68
|
-
- Single checkpoint model (latest session-state only)
|
|
47
|
+
Check available memories with `mcp__serena__list_memories` if helpful.
|