Graphql
This is my personal configuration of skills as a Ruby on Rails Dev
npx -y skills add igmarin/rails-agent-skills --skill graphqlAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 22 stars22 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Orchestrates end-to-end GraphQL API development across four hard-gated phases: (1) domain modeling — mapping entities→Types, actions→Mutations, with bounded context ownership; (2) schema design — field-level authorization, cursor pagination, and structured error handling; (3) TDD — tests must fail before implementation and full suite must pass after; (4) security review — query depth/complexity limits, rate limiting, N+1 elimination, and error sanitization. Use when building GraphQL APIs, adding GraphQL endpoints, or implementing GraphQL features with proper domain boundaries and security. Trigger: GraphQL API, GraphQL schema, GraphQL mutation, GraphQL query, add GraphQL endpoint, implement GraphQL.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
6.2 KB, as published. Nobody here has run it
GraphQL Persona
Agent Phases
Phase 1: Domain Modeling
Steps:
- Map each domain entity and action to a GraphQL type or mutation, assigning it to a single owning bounded context
- Document entity relationships as GraphQL connections or nested types with explicit ownership
Example Domain → Schema Mapping:
| Domain Concept | GraphQL Construct | Owning Context |
|---|---|---|
| Order (entity) | Types::OrderType | Orders |
| Customer (entity) | Types::CustomerType | Accounts |
| PlaceOrder (command) | Mutations::PlaceOrder | Orders |
| Order.lineItems | Types::LineItemType (connection) | Orders |
HARD GATE — Domain Language:
- Core GraphQL types and their owning bounded contexts identified
- Entity relationships mapped to GraphQL connections or nested types
If gate fails: Return to domain discovery.
Phase 2: Schema Design
Steps:
- Use cursor-based or offset pagination for all list fields — never return unbounded arrays
- Enforce field-level authorization via
authorized?on sensitive types and fields (see Phase 4 for the full security checklist) - Wrap mutation responses in a result object with a structured
errorsfield - Validate schema correctness before proceeding
HARD GATE — Schema Validation:
Verify schema validity using graphql-ruby's built-in tools:
namespace :graphql do
task validate: :environment do
puts MySchema.to_definition
puts "Schema valid."
end
end
bundle exec rake graphql:validate
- No circular type references
- All types have proper fields and arguments
- Authorization rules defined for sensitive fields
Example Type:
module Types
class OrderType < Types::BaseObject
field :id, ID, null: false
field :customer, Types::CustomerType, null: false
field :total, Float, null: false
field :status, String, null: false
def self.authorized?(object, context)
context[:current_user].can_read?(object)
end
end
end
Phase 3: TDD Implementation
For every resolver or mutation:
- Write a failing resolver spec, mutation spec, or integration spec targeting the specific graphql-ruby class under test
- Propose implementation, wait for explicit user approval, then implement the resolver/mutation code
- Run the full suite to confirm no regressions
HARD GATE — Test Verification:
- Test EXISTS and RUNS
- Test FAILS before implementation (correct reason)
- Test PASSES after implementation
- Full test suite PASSES (no regressions)
Example Resolver Test:
RSpec.describe Resolvers::OrderResolver do
let(:user) { create(:user) }
let(:order) { create(:order, customer: user) }
it 'returns order for authorized user' do
result = described_class.new(object: nil, context: { current_user: user }).resolve(id: order.id)
expect(result).to eq(order)
end
it 'returns nil for unauthorized user' do
result = described_class.new(object: nil, context: { current_user: create(:user) }).resolve(id: order.id)
expect(result).to be_nil
end
end
Phase 4: Security Review
This is the authoritative phase for all authorization and security requirements.
Steps:
- Audit authorization at field level — every sensitive field must have an
authorized?guard - Configure query depth and complexity limits on the schema class
- Implement rate limiting at the application layer
- Eliminate N+1 queries using
GraphQL::Batchordataloader - Ensure
rescue_fromon the schema class catchesStandardErrorand returns a generic message
HARD GATE — Security Check:
- Authorization on all sensitive fields
- Query depth limit configured (recommended: ≤ 10)
- Query complexity limit configured
- Rate limiting implemented
- No N+1 queries in resolvers
- Error messages sanitized
Example Security Configuration:
class MySchema < GraphQL::Schema
use GraphQL::Batch
query Types::QueryType
mutation Types::MutationType
max_depth 10
max_complexity 100
rescue_from(StandardError) do |err|
raise GraphQL::ExecutionError, "An error occurred"
end
end
Error Recovery
| Problem | Remediation |
|---|---|
| Schema validation fails | Check circular references with MySchema.to_definition; verify all referenced types are defined |
| Authorization bypass detected | Add authorized? to the affected type, write a failing spec, re-run Phase 4 |
| N+1 queries | Identify with bullet gem; add GraphQL::Batch loader or dataloader for the association |
Anti-Patterns
- God schema: Use
app/graphql/types/,app/graphql/mutations/,app/graphql/resolvers/— not one file - Leaking internals: Never expose ActiveRecord column names directly — map to domain-appropriate field names
- Fat resolvers: Extract business logic to service objects; resolvers should only coordinate