From 77adaad441a428c47e70e293b3f91972b85a07a5 Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Sun, 29 Mar 2026 19:44:37 +0300 Subject: [PATCH] =?UTF-8?q?chore(skills):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81=D0=BA=D0=B8=D0=BB=D0=BB=D1=8B?= =?UTF-8?q?=20docstring=20=D0=B8=20security-audit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - напоминание моделям про Google-style docstring'ы и Ruff-конфиг. - чеклист безопасности для ревью кода и зависимостей. - Что: - добавлен docstring (DeerHide): вычищены мёртвые ссылки, добавлен Ruff select, правило языка проекта. - добавлен security-audit: чеклист OWASP, severity-уровни, формат отчёта. - убраны test-generator (Node.js стек) и api-docs (избыточен). - Проверка: - ls agents/.agents/skills/{docstring,security-audit}/SKILL.md. Co-Authored-By: Claude Opus 4.6 (1M context) --- agents/.agents/skills/docstring/SKILL.md | 445 ++++++++++++++++++ agents/.agents/skills/security-audit/SKILL.md | 228 +++++++++ 2 files changed, 673 insertions(+) create mode 100644 agents/.agents/skills/docstring/SKILL.md create mode 100644 agents/.agents/skills/security-audit/SKILL.md diff --git a/agents/.agents/skills/docstring/SKILL.md b/agents/.agents/skills/docstring/SKILL.md new file mode 100644 index 0000000..292b571 --- /dev/null +++ b/agents/.agents/skills/docstring/SKILL.md @@ -0,0 +1,445 @@ +--- +name: python-docstring +description: A skill for writing consistent, well-structured Python docstrings following the Google style convention. +metadata: + author: Deerhide + version: 1.0.0 +--- + +# Python Docstring Skill + +## When to use this skill? + +- Use this skill when writing or updating Python documentation strings (docstrings). +- This skill is useful for ensuring consistent documentation across a Python codebase. +- It should be applied when documenting modules, classes, functions, methods, and attributes. +- Use it during code reviews to verify docstring quality and completeness. + +# Language + +Язык docstring'ов определяется по проекту: если в существующем коде комментарии и docstring'ы на русском — пиши на русском, если на английском — на английском. Не смешивай языки внутри одного проекта. + +# Docstring Style Convention + +We follow the **Google style** docstring convention. This style is chosen for its: +- Readability and clean formatting +- Wide adoption in the Python community +- Excellent support in documentation tools (Sphinx, MkDocs) +- Native support in linting tools (Ruff, Pylint) + +# Module Docstrings + +Every Python module should start with a docstring describing its purpose. + +```python +"""Module for handling user authentication and session management. + +This module provides utilities for user authentication, token generation, +and session lifecycle management. It integrates with OAuth2 providers +and supports JWT-based authentication. + +Example: + Basic usage of the authentication service:: + + from auth import AuthService + + service = AuthService(secret_key="my-secret") + token = service.create_token(user_id=123) + +Attributes: + DEFAULT_TOKEN_EXPIRY (int): Default token expiration time in seconds. + SUPPORTED_ALGORITHMS (list): List of supported JWT algorithms. + +Todo: + * Add support for refresh tokens + * Implement rate limiting for failed attempts +""" + +DEFAULT_TOKEN_EXPIRY = 3600 +SUPPORTED_ALGORITHMS = ["HS256", "RS256"] +``` + +# Class Docstrings + +Class docstrings should describe the class purpose and list its attributes. + +```python +class UserRepository: + """Repository for managing user data persistence. + + This class provides CRUD operations for user entities and handles + database connections and transactions. + + Attributes: + connection: Database connection instance. + table_name: Name of the users table. + cache_enabled: Whether caching is enabled for queries. + + Example: + Creating and using a repository:: + + repo = UserRepository(connection=db_conn) + user = repo.find_by_id(user_id=42) + repo.save(user) + """ + + def __init__(self, connection: DatabaseConnection) -> None: + """Initialize the UserRepository. + + Args: + connection: Active database connection to use for operations. + """ + self.connection = connection + self.table_name = "users" + self.cache_enabled = True +``` + +# Function and Method Docstrings + +Functions and methods should document their purpose, arguments, return values, and exceptions. + +## Basic Function + +```python +def calculate_discount(price: float, percentage: float) -> float: + """Calculate the discounted price. + + Args: + price: Original price of the item. + percentage: Discount percentage (0-100). + + Returns: + The discounted price after applying the percentage reduction. + + Raises: + ValueError: If percentage is not between 0 and 100. + TypeError: If price or percentage are not numeric. + + Example: + >>> calculate_discount(100.0, 20) + 80.0 + """ + if not 0 <= percentage <= 100: + raise ValueError("Percentage must be between 0 and 100") + return price * (1 - percentage / 100) +``` + +## Method with Complex Arguments + +```python +def create_user( + self, + username: str, + email: str, + *, + role: str = "user", + metadata: dict[str, Any] | None = None, +) -> User: + """Create a new user in the system. + + Creates a user entity with the provided information and persists + it to the database. Sends a welcome email upon successful creation. + + Args: + username: Unique username for the new user. Must be alphanumeric + and between 3-50 characters. + email: Valid email address for the user. + role: User role assignment. Defaults to "user". + Valid options are "user", "admin", "moderator". + metadata: Optional dictionary of additional user metadata. + Keys must be strings, values can be any JSON-serializable type. + + Returns: + The newly created User instance with assigned ID. + + Raises: + DuplicateUserError: If username or email already exists. + ValidationError: If input validation fails. + DatabaseError: If database operation fails. + + Note: + This method triggers a background task for sending the welcome email. + The email sending is non-blocking and failures are logged but not raised. + + Example: + Creating a basic user:: + + user = service.create_user( + username="johndoe", + email="john@example.com" + ) + + Creating an admin user with metadata:: + + admin = service.create_user( + username="admin", + email="admin@example.com", + role="admin", + metadata={"department": "IT"} + ) + """ +``` + +## Async Functions + +```python +async def fetch_user_data(user_id: int, timeout: float = 30.0) -> UserData: + """Fetch user data from the remote service. + + Asynchronously retrieves user information from the external API + with automatic retry logic for transient failures. + + Args: + user_id: Unique identifier of the user to fetch. + timeout: Maximum time in seconds to wait for response. + Defaults to 30.0 seconds. + + Returns: + UserData object containing the user's information. + + Raises: + UserNotFoundError: If no user exists with the given ID. + TimeoutError: If the request exceeds the timeout duration. + ServiceUnavailableError: If the remote service is unreachable. + """ +``` + +# Generator and Iterator Docstrings + +```python +def paginate_results( + query: Query, + page_size: int = 100, +) -> Iterator[list[Record]]: + """Paginate through query results. + + Yields pages of records from the query, handling cursor-based + pagination automatically. + + Args: + query: Database query to paginate. + page_size: Number of records per page. Defaults to 100. + + Yields: + Lists of Record objects, each list containing up to page_size items. + + Example: + >>> for page in paginate_results(query, page_size=50): + ... process_records(page) + """ +``` + +# Property Docstrings + +```python +@property +def full_name(self) -> str: + """Return the full name of the user. + + Combines first_name and last_name with proper spacing. + Returns an empty string if both names are unset. + """ + return f"{self.first_name} {self.last_name}".strip() + + +@property +def is_active(self) -> bool: + """Return whether the user account is currently active. + + An account is considered active if it has been verified + and has not been suspended or deleted. + """ + return self.verified and not self.suspended +``` + +# Context Manager Docstrings + +```python +@contextmanager +def database_transaction( + connection: Connection, + isolation_level: str = "READ_COMMITTED", +) -> Iterator[Transaction]: + """Context manager for database transactions. + + Provides automatic commit on success and rollback on failure. + Nested transactions are supported via savepoints. + + Args: + connection: Active database connection. + isolation_level: Transaction isolation level. + Options: "READ_UNCOMMITTED", "READ_COMMITTED", + "REPEATABLE_READ", "SERIALIZABLE". + Defaults to "READ_COMMITTED". + + Yields: + Transaction object for executing queries. + + Raises: + TransactionError: If transaction cannot be started. + + Example: + >>> with database_transaction(conn) as tx: + ... tx.execute("INSERT INTO users VALUES (?)", [user]) + """ +``` + +# Dataclass and Pydantic Model Docstrings + +```python +@dataclass +class OrderItem: + """Represents a single item in an order. + + Attributes: + product_id: Unique identifier of the product. + quantity: Number of units ordered. Must be positive. + unit_price: Price per unit in the order currency. + discount: Applied discount as a decimal (0.0-1.0). + """ + + product_id: str + quantity: int + unit_price: Decimal + discount: Decimal = Decimal("0.0") + + +class UserSettings(BaseModel): + """User preference settings. + + Stores user-configurable settings for the application, + including notification preferences and display options. + + Attributes: + theme: UI theme preference. Either "light" or "dark". + notifications_enabled: Whether to send notifications. + language: Preferred language code (ISO 639-1). + timezone: User's timezone (IANA format). + """ + + theme: Literal["light", "dark"] = "light" + notifications_enabled: bool = True + language: str = "en" + timezone: str = "UTC" +``` + +# Enum Docstrings + +```python +class OrderStatus(Enum): + """Status values for order lifecycle. + + Attributes: + PENDING: Order created but not yet processed. + CONFIRMED: Order confirmed and awaiting fulfillment. + SHIPPED: Order has been shipped to customer. + DELIVERED: Order successfully delivered. + CANCELLED: Order was cancelled before fulfillment. + """ + + PENDING = "pending" + CONFIRMED = "confirmed" + SHIPPED = "shipped" + DELIVERED = "delivered" + CANCELLED = "cancelled" +``` + +# Exception Docstrings + +```python +class ValidationError(Exception): + """Raised when input validation fails. + + This exception is raised when user input or API request data + fails validation rules. + + Attributes: + field: Name of the field that failed validation. + message: Human-readable error message. + code: Machine-readable error code for client handling. + + Example: + >>> raise ValidationError( + ... field="email", + ... message="Invalid email format", + ... code="INVALID_EMAIL" + ... ) + """ + + def __init__(self, field: str, message: str, code: str) -> None: + """Initialize ValidationError. + + Args: + field: Name of the field that failed validation. + message: Human-readable description of the error. + code: Machine-readable error code. + """ + self.field = field + self.message = message + self.code = code + super().__init__(f"{field}: {message}") +``` + +# Docstring Sections Reference + +The following sections are supported in Google style docstrings: + +| Section | Purpose | +|---------|---------| +| `Args:` | Document function/method parameters | +| `Returns:` | Describe the return value | +| `Yields:` | Describe yielded values (generators) | +| `Raises:` | List exceptions that may be raised | +| `Attributes:` | Document class/module attributes | +| `Example:` / `Examples:` | Provide usage examples | +| `Note:` | Additional information or caveats | +| `Warning:` | Important warnings for users | +| `Todo:` | Future improvements or tasks | +| `See Also:` | References to related functions/classes | + +# Best Practices + +1. **Be Concise**: First line should be a brief summary under 79 characters. +2. **Use Imperative Mood**: Write "Calculate the sum" not "Calculates the sum". +3. **Document All Public APIs**: Every public function, class, and method needs a docstring. +4. **Rely on Type Hints**: Avoid duplicating type information in docstrings when type hints are present. Modern documentation tools extract types from annotations. +5. **Provide Examples**: Complex functions benefit from usage examples. +6. **Document Exceptions**: List all exceptions that can be raised. +7. **Keep Updated**: Update docstrings when code changes. +8. **Use Proper Indentation**: Continuation lines should be indented consistently. + +# Linting Configuration + +Recommended Ruff configuration for `pyproject.toml`: + +```toml +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +select = ["D", "F", "E", "W", "I", "UP", "B", "SIM", "S", "A", "C90", "RET", "PERF"] + +[tool.ruff.lint.pydocstyle] +convention = "google" +``` + +Key rule groups: **D** (docstrings), **F** (pyflakes), **E/W** (pycodestyle), +**I** (imports), **UP** (pyupgrade), **B** (bugbear), **SIM** (simplify), +**S** (security/bandit), **A** (builtins shadowing), **C90** (complexity), +**RET** (return statements), **PERF** (performance). + +# Common Ruff Docstring Rules + +| Rule | Description | +|------|-------------| +| D100 | Missing docstring in public module | +| D101 | Missing docstring in public class | +| D102 | Missing docstring in public method | +| D103 | Missing docstring in public function | +| D107 | Missing docstring in `__init__` | +| D200 | One-line docstring should fit on one line | +| D205 | 1 blank line required between summary and description | +| D400 | First line should end with a period | +| D401 | First line should be in imperative mood | +| D417 | Missing argument descriptions in docstring | + diff --git a/agents/.agents/skills/security-audit/SKILL.md b/agents/.agents/skills/security-audit/SKILL.md new file mode 100644 index 0000000..2b7e179 --- /dev/null +++ b/agents/.agents/skills/security-audit/SKILL.md @@ -0,0 +1,228 @@ +--- +name: security-audit +description: Audit code and dependencies for security vulnerabilities. Use when reviewing PRs, checking dependencies, preparing for deployment, or when user mentions security, vulnerabilities, or audit. +--- + +# Security Audit Skill + +Perform comprehensive security audits on codebases to identify vulnerabilities before they reach production. + +## When to Use This Skill + +- User mentions "security", "audit", "vulnerability", "CVE" +- Before deployment commands +- During PR reviews +- User asks about dependencies +- Periodic security checks + +## Audit Checklist + +### 1. Secrets Exposure + +**Check for hardcoded secrets:** +```bash +# Search for common secret patterns +grep -rn "API_KEY\|SECRET\|TOKEN\|PASSWORD" --include="*.{js,ts,py,go,rb,java}" . +grep -rn "sk-\|pk_\|api_\|secret_" --include="*.{js,ts,py,go,rb,java}" . +``` + +**Verify .gitignore:** +```bash +# Ensure sensitive files are ignored +cat .gitignore | grep -E "\.env|secret|credential|\.pem|\.key" +``` + +**Check git history for leaked secrets:** +```bash +# Search recent commits (requires git-secrets or truffleHog) +git log -p --all -S "API_KEY" --since="30 days ago" +``` + +✅ Pass criteria: +- No hardcoded API keys, tokens, or passwords +- `.env` files in `.gitignore` +- No secrets in git history + +### 2. Dependency Vulnerabilities + +**Node.js:** +```bash +npm audit +# or +yarn audit +# or +pnpm audit +``` + +**Python:** +```bash +pip-audit +# or +safety check +``` + +**Go:** +```bash +govulncheck ./... +``` + +**Rust:** +```bash +cargo audit +``` + +✅ Pass criteria: +- No critical vulnerabilities +- No high vulnerabilities > 30 days old +- Dependencies updated within last 90 days + +### 3. Input Validation + +**Check for:** +- User inputs sanitized before use +- SQL queries use parameterized statements +- File paths validated and sandboxed +- HTML content escaped before rendering +- Command injection prevention + +**Common vulnerable patterns:** +```javascript +// BAD: SQL injection +db.query(`SELECT * FROM users WHERE id = ${userId}`) + +// GOOD: Parameterized query +db.query('SELECT * FROM users WHERE id = ?', [userId]) +``` + +```python +# BAD: Command injection +os.system(f"convert {user_file}") + +# GOOD: Use subprocess with list +subprocess.run(["convert", user_file], check=True) +``` + +### 4. Authentication & Authorization + +**Check for:** +- Passwords hashed with bcrypt/argon2 (not MD5/SHA1) +- Session tokens are cryptographically random +- Sessions expire appropriately +- CSRF protection on state-changing endpoints +- Rate limiting on auth endpoints +- Account lockout after failed attempts + +**Look for:** +```javascript +// BAD: Weak hashing +crypto.createHash('md5').update(password) + +// GOOD: Bcrypt +bcrypt.hash(password, 12) +``` + +### 5. HTTPS & Transport Security + +**Check for:** +- HTTPS enforced (HSTS header) +- Secure cookie flags (`Secure`, `HttpOnly`, `SameSite`) +- No mixed content warnings +- TLS 1.2+ required + +### 6. Error Handling + +**Check for:** +- Stack traces not exposed in production +- Generic error messages for users +- Detailed errors only in logs +- Sensitive data not in error messages + +```javascript +// BAD: Exposes internals +res.status(500).send({ error: err.stack }) + +// GOOD: Generic message +res.status(500).send({ error: 'An unexpected error occurred' }) +``` + +### 7. File Upload Security + +If file uploads exist: +- Validate file type server-side (not just extension) +- Limit file size +- Scan for malware +- Store outside webroot +- Rename uploaded files + +### 8. API Security + +- Authentication required on all sensitive endpoints +- Authorization checks per resource +- Rate limiting implemented +- CORS configured restrictively +- API versioning in place + +## Severity Levels + +| Level | Description | Action Required | +|-------|-------------|-----------------| +| 🔴 Critical | Actively exploitable | Block deployment | +| 🟠 High | Exploitable with effort | Fix within 7 days | +| 🟡 Medium | Requires conditions | Fix within 30 days | +| 🟢 Low | Minimal impact | Fix when convenient | + +## Output Format + +```markdown +## Security Audit Results + +**Project:** [name] +**Date:** [date] +**Auditor:** Claude (automated) + +### Summary + +| Severity | Count | +|----------|-------| +| 🔴 Critical | 0 | +| 🟠 High | 1 | +| 🟡 Medium | 2 | +| 🟢 Low | 3 | + +### Findings + +#### 1. [🟠 High] Hardcoded API Key + +**Location:** `src/config.js:15` +**Description:** API key for payment provider is hardcoded +**Risk:** If source code is leaked, attackers gain API access +**Recommendation:** Move to environment variable + +```diff +- const STRIPE_KEY = 'sk_live_abc123...' ++ const STRIPE_KEY = process.env.STRIPE_SECRET_KEY +``` + +#### 2. [🟡 Medium] Missing Rate Limiting + +**Location:** `src/routes/auth.js` +**Description:** Login endpoint has no rate limiting +**Risk:** Enables brute force attacks +**Recommendation:** Add rate limiting middleware + +### Recommendations + +1. [ ] Fix critical and high issues before next deployment +2. [ ] Schedule medium issues for next sprint +3. [ ] Add low issues to backlog +4. [ ] Re-run audit after fixes +``` + +## Commands to Run + +After completing the audit, provide the user with: + +1. Summary of findings +2. Prioritized fix list +3. Commands to address each issue +4. Timeline recommendation