CHANGELOG.md

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.2.1] - 2026-05-13

### Fixed
- **Hex publish compatibility** — Replaced `inflex` (GitHub dep, blocked hex.publish) with
  `plurality` (Hex dep) for route name singularization. Plurality is a modern, zero-regex
  inflection library with verified accuracy across 80k+ noun pairs.

### Changed
- `mix.exs` dependency: `inflex` → `plurality ~> 0.2`
- `RouteIntrospection.singularize/1` now calls `Plurality.singularize/1` directly

## [1.2.0] - 2026-05-13

### Added
- **MCP Resources for schema discovery** — Each `expose`d schema now automatically registers an MCP resource at `ectomancer://schemas/{name}` returning full schema metadata (fields, types, associations, primary key, available actions). A top-level `ectomancer://schemas` resource lists all registered schemas. Opt-out per schema with `resource: false`. (Closes #56)
- **Dynamic association preloading** — New `preloadable` option for `expose` allows LLMs to dynamically request associated records via an `include` parameter on `list` and `get` tools. Supports `preloadable: true` (all associations) or `preloadable: [:posts, :comments]` (specific). Requested includes are validated against allowed associations. (Closes #57)
- **Rate limiting** — Token bucket algorithm with ETS storage. Configurable per-tool and global limits. Opt-in via `config :ectomancer, :rate_limits`.
- **Multi-repo support** — expose schemas from different repos with `expose User, repo: MyApp.ReplicaRepo`. Falls back to global repo config.
- **Browser MCP client** — Zero-dependency HTML browser client at `priv/ectomancer.html`. Browse tools, call them, see results. No build step required.
- **Auto-deployed ExDoc to GitHub Pages** — New CI workflow builds docs on push to main and deploys via `actions/deploy-pages`.
- **CI, Hex, and Docs badges** to README header.

### Fixed
- `singularize` helper now handles edge cases (`status`, `address`, `series`) correctly.
- Error handling now returns structured `{:error, %{code:, message:, details:}}` tuples consistently.

### Testing
- **426 tests** (up from 260), all passing
- 28 new tests: 19 for MCP Resources, 9 for dynamic preloading
- 9 new rate limiter tests
- Validated multi-repo integration with secondary Phoenix app (SQLite)

## [1.1.0] - 2026-04-23

### Added
- Interactive setup tool (`mix ectomancer.setup`) for automatic project configuration
  - Auto-discovers Ecto schemas via module introspection and file scanning
  - Prompts for schema selection, Oban bridge, and tool namespace
  - Generates MCP module with proper `expose` declarations
  - Updates mix.exs, config.exs, and router files automatically
  - Derives module name from app name (e.g., `TestEctoApp.MCP`)
- Schema discovery module (`Ectomancer.Installer.SchemaDiscovery`) with dual discovery strategy
- Config updater (`Ectomancer.Installer.ConfigUpdater`) for idempotent file patching
- Dependency checker (`Ectomancer.Installer.DependencyChecker`) for required/optional dep validation
- Template renderer (`Ectomancer.Installer.TemplateRenderer`) for MCP module generation
- Igniter installer stub (`Ectomancer.Igniter`)

### Testing
- **260 tests** (up from 223), all passing
- Full integration tests for the setup tool workflow

## [1.0.0] - 2026-03-29

### 🎉 Official v1.0.0 Release - Production Ready!

Ectomancer is now officially stable and ready for production use! Three phases of development complete.

### Added

#### Optional Oban Bridge (Issue #15) - Phase 3 Final Feature!
- New `expose_oban_jobs/0` and `expose_oban_jobs/1` macros for Oban integration
- Automatically generates 5 MCP tools for job queue management:
  - `list_oban_queues` - List all queues with job statistics (total, executing, available, retryable, discarded)
  - `get_queue_depth` - Get detailed counts for a specific queue
  - `list_stuck_jobs` - Find executing jobs with optional filters (queue, worker, min_age, limit)
  - `retry_job` - Retry failed or discarded jobs by ID
  - `cancel_job` - Cancel or delete jobs by ID
- Only activates when Oban is in dependencies (optional dependency support)
- Supports `:namespace` option for tool naming (e.g., `background_list_oban_queues`)
- Comprehensive test coverage (13 tests)

```elixir
# Expose all Oban job management tools
expose_oban_jobs

# With namespace prefix
expose_oban_jobs(namespace: :background)
# Generates: background_list_oban_queues, background_get_queue_depth, etc.
```

#### Phoenix Route Introspection (Issue #14) - Phase 3 Complete!
- New `expose_routes/1` macro to auto-generate MCP tools from Phoenix router
- Support for all HTTP methods: GET, POST, PUT, PATCH, DELETE
- Smart tool naming with automatic singularization:
  - `/users` → `get_users`, `post_users`
  - `/users/:id` → `get_user`, `put_user`, `delete_user`
- Route filtering options:
  - `:only` - Include only specific paths
  - `:except` - Exclude specific paths  
  - `:methods` - Filter by HTTP methods
  - `:namespace` - Prefix tool names (e.g., `api_get_users`)
- Automatic path parameter mapping to tool parameters
- Direct controller action execution via `Plug.Test.conn`
- Proper handling of `Plug.Conn.AlreadySentError`

```elixir
# Expose all routes
expose_routes MyAppWeb.Router

# With filtering
expose_routes MyAppWeb.Router,
  only: ["/api/users"],
  namespace: :api,
  methods: ["GET", "POST"]
```

### Testing
- **223 tests** (up from 193)
- **30 new tests**: 13 for Oban bridge, 17 for route introspection
- Full integration tested with sweetcorn Phoenix app including:
  - Oban job insertion, retry, and cancellation via MCP tools
  - Route tool execution through Phoenix controllers
  - All authorization strategies working with new features

### Issues Closed
- [#15](https://github.com/GustavoZiaugra/ectomancer/issues/15) - Create optional Oban bridge for job queue management
- [#14](https://github.com/GustavoZiaugra/ectomancer/issues/14) - Implement Phoenix route introspection for MCP tools

## [0.1.0-rc.3] - 2026-03-18

### Added

#### Read-Only Mode (Issue #12)
- New `:readonly` option for `expose/2` macro
- When `readonly: true`, only generates `:list` and `:get` tools
- Prevents create, update, destroy operations
- Perfect for public read-only access to data

```elixir
expose MyApp.Blog.Post, readonly: true
# Generates only: list_posts, get_post
```

#### Changeset Error Mapping (Issue #13)
- Enhanced error messages from Ecto changeset validations
- Automatic categorization of validation errors:
  - **presence**: Missing required fields
  - **format**: Invalid format (email regex, etc.)
  - **inclusion**: Value not in allowed set
  - **confirmation**: Confirmation doesn't match
  - **length**: String length issues
  - **comparison**: Numeric comparison failures

- Improved database error detection:
  - **unique_violation**: "Duplicate value: Record with this value already exists"
  - **foreign_key_violation**: "Invalid reference: Related record does not exist"
  - **not_null_violation**: "Missing required parameter: Field Name"

- Schema changeset integration
  - Uses schema's `changeset/2` function when available
  - Ensures unique_constraint validations work properly
  - Returns structured error responses instead of binary strings

### Changed
- Updated README.md with read-only mode and error handling documentation
- Enhanced error categorization in `format_error/1`

### Fixed
- Fixed unique constraint violations to return proper error responses
- Fixed foreign key violations to show descriptive messages
- Fixed changeset validation errors to show field names and messages

### Testing
- **193 tests** (up from 172)
- **21 new tests**: 16 for read-only mode, 6 for error mapping
- Full integration tested with sweetcorn Phoenix app
- All authorization strategies still working

### Issues Closed
- [#12](https://github.com/GustavoZiaugra/ectomancer/issues/12) - Implement read-only mode for expose macro
- [#13](https://github.com/GustavoZiaugra/ectomancer/issues/13) - Map Ecto changeset errors to MCP error responses

## [0.1.0-rc.2] - 2026-03-17

### Added

#### Authorization System (Phase 2)
- **Inline function authorization** - Simple auth checks with inline functions
  ```elixir
  authorize fn actor, action -> actor.role == :admin end
  ```
- **Policy module authorization** - Reusable authorization logic via behavior
  ```elixir
  authorize with: MyApp.Policies.UserPolicy
  ```
- **Public access** - `:none` authorization for public endpoints
  ```elixir
  authorize :none
  ```
- **Per-schema authorization** - Global auth rules for all actions on a schema
- **Per-action authorization** - Fine-grained control with action-specific rules
- **Authorization cascade** - Multiple auth levels work together

#### Binary ID / UUID Support
- Full support for `binary_id` primary keys
- Automatic UUID string casting
- Works with all CRUD operations

#### Enhanced Error Messages
- Descriptive error messages (e.g., "Missing required parameter: User id")
- Proper MCP error codes (-32602 for validation, -32603 for internal)
- Field identification in error responses

### Changed
- Updated README.md with comprehensive authorization documentation
- Improved error handling with better error categorization

### Fixed
- Fixed binary_id primary key handling in get/update/destroy operations
- Fixed Peri validation compatibility with JSON Schema format
- Fixed tool parameter generation for nested blocks
- Fixed atom vs string key handling in normalize_params

### Security
- SQL injection prevention via parameterized queries
- Row limits to prevent memory exhaustion (100 records default)
- Authorization checks before tool execution
- Proper error messages without exposing internal details

### Testing
- **172 tests** (up from 128)
- **35 authorization-specific tests**
- All authorization strategies tested
- Full integration tested with sweetcorn Phoenix app

### Issues Closed
- [#10](https://github.com/GustavoZiaugra/ectomancer/issues/10) - Design and implement authorization hook system
- [#11](https://github.com/GustavoZiaugra/ectomancer/issues/11) - Add per-schema and per-action authorization granularity
- [#35](https://github.com/GustavoZiaugra/ectomancer/issues/35) - Fix critical bugs in binary ID handling and tool parameter schemas

## [0.1.0-rc.1] - 2026-03-16

### Added
- First release candidate with fully functional CRUD operations
- Core MCP server implementation via `Ectomancer` module
- `expose/2` macro for auto-generating CRUD tools from Ecto schemas (list, get, create, update, destroy)
- `tool/2` macro for custom tool definitions with param validation
- `Ectomancer.Plug` for seamless Phoenix router integration
- `Ectomancer.Repo` abstraction supporting all major CRUD operations
- Automatic actor extraction and threading through `conn.assigns`
- Field filtering support via `:only` and `:except` options
- Namespace support to prevent tool naming collisions
- Comprehensive test suite (128 tests, all passing)
- Full Credo and Dialyzer compliance
- Support for Phoenix 1.7 and 1.8
- MIT License

### Fixed
- Fixed Peri schema validation crashes by disabling params in exposed tools
- Fixed GenServer crashes during CRUD operations with proper error handling
- Fixed tool execution to return proper Anubis Response format
- Fixed repo error handling with comprehensive try/rescue blocks

### Security
- SQL injection prevention via parameterized queries in Repo operations
- Row limits to prevent memory exhaustion (100 records default)
- Proper error messages without exposing internal details

[Unreleased]: https://github.com/GustavoZiaugra/ectomancer/compare/v1.2.1...HEAD
[1.2.1]: https://github.com/GustavoZiaugra/ectomancer/compare/v1.2.0...v1.2.1
[1.2.0]: https://github.com/GustavoZiaugra/ectomancer/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/GustavoZiaugra/ectomancer/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/GustavoZiaugra/ectomancer/releases/tag/v1.0.0
[0.1.0-rc.4]: https://github.com/GustavoZiaugra/ectomancer/releases/tag/v0.1.0-rc.4
[0.1.0-rc.3]: https://github.com/GustavoZiaugra/ectomancer/releases/tag/v0.1.0-rc.3
[0.1.0-rc.2]: https://github.com/GustavoZiaugra/ectomancer/releases/tag/v0.1.0-rc.2
[0.1.0-rc.1]: https://github.com/GustavoZiaugra/ectomancer/releases/tag/v0.1.0-rc.1