kodelyth-ecc 1.5.4 → 1.5.6

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.
@@ -0,0 +1,26 @@
1
+ ---
2
+ paths:
3
+ - "**/*.ex"
4
+ - "**/*.exs"
5
+ ---
6
+ # Elixir Hooks
7
+
8
+ > This file extends [common/hooks.md](../common/hooks.md) with Elixir specific content.
9
+
10
+ ## PostToolUse Hooks
11
+
12
+ Configure in `~/.claude/settings.json`:
13
+
14
+ - **mix format**: Auto-format `.ex` / `.exs` files after edit
15
+ ```bash
16
+ mix format <file>
17
+ ```
18
+ - **Credo**: Run on edited files for style warnings
19
+ ```bash
20
+ mix credo <file>
21
+ ```
22
+
23
+ ## Warnings
24
+
25
+ - Warn when `IO.inspect` is left in non-test `.ex` files (use `Logger` instead)
26
+ - Warn when `dbg()` (Elixir 1.14+) is left in production code paths
@@ -0,0 +1,67 @@
1
+ ---
2
+ paths:
3
+ - "**/*.ex"
4
+ - "**/*.exs"
5
+ ---
6
+ # Elixir Patterns
7
+
8
+ > This file extends [common/patterns.md](../common/patterns.md) with Elixir specific content.
9
+
10
+ ## with for Multi-Step Operations
11
+
12
+ ```elixir
13
+ def create_user(params) do
14
+ with {:ok, validated} <- validate(params),
15
+ {:ok, user} <- Repo.insert(User.changeset(%User{}, validated)),
16
+ :ok <- send_welcome_email(user) do
17
+ {:ok, user}
18
+ end
19
+ end
20
+ ```
21
+
22
+ ## GenServer Pattern
23
+
24
+ ```elixir
25
+ defmodule MyApp.Cache do
26
+ use GenServer
27
+
28
+ def start_link(opts), do: GenServer.start_link(__MODULE__, %{}, opts)
29
+
30
+ def get(pid, key), do: GenServer.call(pid, {:get, key})
31
+ def put(pid, key, value), do: GenServer.cast(pid, {:put, key, value})
32
+
33
+ @impl true
34
+ def init(state), do: {:ok, state}
35
+
36
+ @impl true
37
+ def handle_call({:get, key}, _from, state), do: {:reply, Map.get(state, key), state}
38
+
39
+ @impl true
40
+ def handle_cast({:put, key, value}, state), do: {:noreply, Map.put(state, key, value)}
41
+ end
42
+ ```
43
+
44
+ ## Context Modules (Phoenix)
45
+
46
+ ```elixir
47
+ defmodule MyApp.Accounts do
48
+ alias MyApp.Accounts.User
49
+ alias MyApp.Repo
50
+
51
+ def get_user!(id), do: Repo.get!(User, id)
52
+
53
+ def create_user(attrs) do
54
+ %User{}
55
+ |> User.changeset(attrs)
56
+ |> Repo.insert()
57
+ end
58
+ end
59
+ ```
60
+
61
+ ## Tagged Tuples for Errors
62
+
63
+ Always return `{:ok, result}` or `{:error, reason}` — never bare values from functions that can fail.
64
+
65
+ ## Reference
66
+
67
+ See skill: `phoenix-patterns` for Phoenix LiveView, contexts, and Ecto query patterns.
@@ -0,0 +1,58 @@
1
+ ---
2
+ paths:
3
+ - "**/*.ex"
4
+ - "**/*.exs"
5
+ ---
6
+ # Elixir Security
7
+
8
+ > This file extends [common/security.md](../common/security.md) with Elixir specific content.
9
+
10
+ ## Secret Management
11
+
12
+ ```elixir
13
+ # config/runtime.exs — read from environment at runtime, never compile-time
14
+ config :my_app, :stripe_key,
15
+ System.fetch_env!("STRIPE_SECRET_KEY") # raises if missing
16
+ ```
17
+
18
+ Never put secrets in `config/config.exs` or `config/dev.exs` committed to git.
19
+
20
+ ## SQL Injection
21
+
22
+ Always use Ecto parameterized queries:
23
+
24
+ ```elixir
25
+ # UNSAFE — never do this
26
+ Repo.query("SELECT * FROM users WHERE email = '#{email}'")
27
+
28
+ # SAFE
29
+ from(u in User, where: u.email == ^email) |> Repo.one()
30
+ ```
31
+
32
+ ## Atom Exhaustion
33
+
34
+ Never convert untrusted user input to atoms — the atom table is not garbage collected:
35
+
36
+ ```elixir
37
+ # UNSAFE
38
+ String.to_atom(user_input)
39
+
40
+ # SAFE
41
+ String.to_existing_atom(user_input) # only if atom must already exist
42
+ # or keep it as a string
43
+ ```
44
+
45
+ ## Security Scanning
46
+
47
+ - **Sobelow** for Phoenix/Elixir static security analysis:
48
+ ```bash
49
+ mix sobelow --config
50
+ ```
51
+ - **mix audit** for dependency vulnerability scanning:
52
+ ```bash
53
+ mix hex.audit
54
+ ```
55
+
56
+ ## Reference
57
+
58
+ See skill: `security-review` for OWASP top 10 and authentication patterns.
@@ -0,0 +1,64 @@
1
+ ---
2
+ paths:
3
+ - "**/*.ex"
4
+ - "**/*.exs"
5
+ - "**/test/**"
6
+ ---
7
+ # Elixir Testing
8
+
9
+ > This file extends [common/testing.md](../common/testing.md) with Elixir specific content.
10
+
11
+ ## Framework
12
+
13
+ Use **ExUnit** (built-in). Use **Mox** for behaviour-based mocking.
14
+
15
+ ## Structure
16
+
17
+ ```elixir
18
+ defmodule MyApp.AccountsTest do
19
+ use MyApp.DataCase
20
+
21
+ alias MyApp.Accounts
22
+
23
+ describe "create_user/1" do
24
+ test "creates a user with valid attrs" do
25
+ attrs = %{name: "Alice", email: "alice@example.com"}
26
+ assert {:ok, user} = Accounts.create_user(attrs)
27
+ assert user.email == "alice@example.com"
28
+ end
29
+
30
+ test "returns error with invalid attrs" do
31
+ assert {:error, changeset} = Accounts.create_user(%{})
32
+ assert "can't be blank" in errors_on(changeset).email
33
+ end
34
+ end
35
+ end
36
+ ```
37
+
38
+ ## Coverage
39
+
40
+ ```bash
41
+ mix test --cover
42
+ ```
43
+
44
+ Use **excoveralls** for detailed coverage reports:
45
+
46
+ ```bash
47
+ mix coveralls
48
+ mix coveralls.html
49
+ ```
50
+
51
+ ## Async Tests
52
+
53
+ Mark tests as `async: true` when they don't share state:
54
+
55
+ ```elixir
56
+ defmodule MyApp.PureTest do
57
+ use ExUnit.Case, async: true
58
+ ...
59
+ end
60
+ ```
61
+
62
+ ## Reference
63
+
64
+ See skill: `elixir-testing` for ExUnit async patterns, Mox setup, and property-based testing with StreamData.
@@ -0,0 +1,41 @@
1
+ ---
2
+ paths:
3
+ - "**/*.rb"
4
+ - "**/*.rake"
5
+ - "**/Gemfile"
6
+ - "**/Rakefile"
7
+ ---
8
+ # Ruby Coding Style
9
+
10
+ > This file extends [common/coding-style.md](../common/coding-style.md) with Ruby specific content.
11
+
12
+ ## Standards
13
+
14
+ - Follow the **Ruby Style Guide** (rubocop default)
15
+ - Use **frozen_string_literal: true** at the top of every file
16
+ - Prefer `do...end` for multi-line blocks, `{ }` for single-line
17
+
18
+ ## Immutability
19
+
20
+ ```ruby
21
+ # frozen_string_literal: true
22
+
23
+ User = Data.define(:name, :email) # Ruby 3.2+ immutable value object
24
+ ```
25
+
26
+ ## Formatting
27
+
28
+ - **RuboCop** for linting and style enforcement
29
+ - **StandardRB** as a zero-config RuboCop config alternative
30
+ - Line length: 120 characters max
31
+
32
+ ## Naming
33
+
34
+ - `snake_case` for methods and variables
35
+ - `CamelCase` for classes and modules
36
+ - `SCREAMING_SNAKE_CASE` for constants
37
+ - Predicate methods end with `?`, destructive methods end with `!`
38
+
39
+ ## Reference
40
+
41
+ See skill: `ruby-patterns` for comprehensive Ruby idioms, Rails patterns, and concurrency.
@@ -0,0 +1,23 @@
1
+ ---
2
+ paths:
3
+ - "**/*.rb"
4
+ - "**/*.rake"
5
+ ---
6
+ # Ruby Hooks
7
+
8
+ > This file extends [common/hooks.md](../common/hooks.md) with Ruby specific content.
9
+
10
+ ## PostToolUse Hooks
11
+
12
+ Configure in `~/.claude/settings.json`:
13
+
14
+ - **RuboCop**: Auto-lint `.rb` files after edit
15
+ ```bash
16
+ rubocop --autocorrect <file>
17
+ ```
18
+ - **Syntax check**: Run `ruby -c <file>` after editing
19
+
20
+ ## Warnings
21
+
22
+ - Warn about `puts` / `p` statements in non-test `.rb` files (use `Rails.logger` or a logger instead)
23
+ - Warn when `binding.pry` or `byebug` is left in edited files
@@ -0,0 +1,71 @@
1
+ ---
2
+ paths:
3
+ - "**/*.rb"
4
+ - "**/*.rake"
5
+ ---
6
+ # Ruby Patterns
7
+
8
+ > This file extends [common/patterns.md](../common/patterns.md) with Ruby specific content.
9
+
10
+ ## Service Objects
11
+
12
+ ```ruby
13
+ # frozen_string_literal: true
14
+
15
+ class CreateUserService
16
+ def initialize(params)
17
+ @params = params
18
+ end
19
+
20
+ def call
21
+ user = User.new(@params)
22
+ user.save!
23
+ user
24
+ end
25
+ end
26
+
27
+ # Usage
28
+ result = CreateUserService.new(params).call
29
+ ```
30
+
31
+ ## Value Objects
32
+
33
+ ```ruby
34
+ # frozen_string_literal: true
35
+
36
+ Address = Data.define(:street, :city, :country)
37
+
38
+ address = Address.new(street: "123 Main St", city: "London", country: "UK")
39
+ ```
40
+
41
+ ## Query Objects
42
+
43
+ ```ruby
44
+ # frozen_string_literal: true
45
+
46
+ class ActiveUsersQuery
47
+ def initialize(relation = User.all)
48
+ @relation = relation
49
+ end
50
+
51
+ def call
52
+ @relation.where(status: :active).order(created_at: :desc)
53
+ end
54
+ end
55
+ ```
56
+
57
+ ## Modules for Composition
58
+
59
+ Prefer composition over inheritance for shared behavior:
60
+
61
+ ```ruby
62
+ module Auditable
63
+ def self.included(base)
64
+ base.before_action :track_activity
65
+ end
66
+ end
67
+ ```
68
+
69
+ ## Reference
70
+
71
+ See skill: `rails-patterns` for Rails-specific patterns including concerns, callbacks, and ActiveRecord best practices.
@@ -0,0 +1,56 @@
1
+ ---
2
+ paths:
3
+ - "**/*.rb"
4
+ - "**/*.rake"
5
+ ---
6
+ # Ruby Security
7
+
8
+ > This file extends [common/security.md](../common/security.md) with Ruby specific content.
9
+
10
+ ## Secret Management
11
+
12
+ ```ruby
13
+ # Never hardcode secrets
14
+ api_key = ENV.fetch("STRIPE_SECRET_KEY") # raises KeyError if missing, not nil
15
+
16
+ # Rails credentials (encrypted)
17
+ Rails.application.credentials.stripe[:secret_key]
18
+ ```
19
+
20
+ ## SQL Injection
21
+
22
+ Always use parameterized queries — never string interpolation:
23
+
24
+ ```ruby
25
+ # UNSAFE
26
+ User.where("email = '#{params[:email]}'")
27
+
28
+ # SAFE
29
+ User.where(email: params[:email])
30
+ User.where("email = ?", params[:email])
31
+ ```
32
+
33
+ ## Mass Assignment
34
+
35
+ Use strong parameters in Rails controllers:
36
+
37
+ ```ruby
38
+ def user_params
39
+ params.require(:user).permit(:name, :email)
40
+ end
41
+ ```
42
+
43
+ ## Security Scanning
44
+
45
+ - **Brakeman** for static security analysis of Rails apps:
46
+ ```bash
47
+ brakeman -q
48
+ ```
49
+ - **bundler-audit** for dependency CVE scanning:
50
+ ```bash
51
+ bundle audit check --update
52
+ ```
53
+
54
+ ## Reference
55
+
56
+ See skill: `security-review` for OWASP top 10 and auth patterns.
@@ -0,0 +1,65 @@
1
+ ---
2
+ paths:
3
+ - "**/*.rb"
4
+ - "**/*_spec.rb"
5
+ - "**/spec/**"
6
+ ---
7
+ # Ruby Testing
8
+
9
+ > This file extends [common/testing.md](../common/testing.md) with Ruby specific content.
10
+
11
+ ## Framework
12
+
13
+ Use **RSpec** as the testing framework. Use **FactoryBot** for fixtures.
14
+
15
+ ## Structure
16
+
17
+ ```ruby
18
+ # frozen_string_literal: true
19
+
20
+ RSpec.describe CreateUserService do
21
+ subject(:service) { described_class.new(params) }
22
+
23
+ let(:params) { { name: "Alice", email: "alice@example.com" } }
24
+
25
+ describe "#call" do
26
+ context "with valid params" do
27
+ it "creates a user" do
28
+ expect { service.call }.to change(User, :count).by(1)
29
+ end
30
+ end
31
+
32
+ context "with invalid params" do
33
+ let(:params) { { name: "", email: "bad" } }
34
+
35
+ it "raises an error" do
36
+ expect { service.call }.to raise_error(ActiveRecord::RecordInvalid)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ ```
42
+
43
+ ## Coverage
44
+
45
+ ```bash
46
+ COVERAGE=true bundle exec rspec
47
+ ```
48
+
49
+ Use **SimpleCov** for coverage reporting. Target 90%+ for new code.
50
+
51
+ ## Factories
52
+
53
+ ```ruby
54
+ FactoryBot.define do
55
+ factory :user do
56
+ sequence(:email) { |n| "user#{n}@example.com" }
57
+ name { Faker::Name.name }
58
+ status { :active }
59
+ end
60
+ end
61
+ ```
62
+
63
+ ## Reference
64
+
65
+ See skill: `ruby-testing` for detailed RSpec patterns, shared examples, and Rails request specs.