Metadata-Version: 2.3
Name: akeneo_mock_server
Version: 0.9.0
Summary: This implements an API that's compatible to Akeneo. If it's not, it's a bug. This is NOT an official Akeneo Product
Requires-Dist: fastapi>=0.159.1
Requires-Dist: httpx>=0.28.1
Requires-Dist: persist-queue[extra]>=1.1.0
Requires-Dist: psycopg[binary,pool]>=3.3.6
Requires-Dist: pydantic>=2.14.1
Requires-Dist: sqlglot>=30.24.0
Requires-Dist: uvicorn>=0.54.0 ; extra == 'run'
Requires-Python: >=3.12
Provides-Extra: run
Description-Content-Type: text/markdown

# Mock Akeneo API

Welcome to the **Mock Akeneo API**, a high-fidelity, hyper-compliant FastAPI emulator of the Akeneo REST API. 

Relation to Akeneo:

THIS IS NOT AN OFFICIAL AKENEO PRODUCT! 

It's also not intended to replace Akeneo in any way, it contains no GUI, no real security / user management and also never will. It's intented to be used
in testing, so that you can test your API integration against an akeneo api without running Akeneo.

## Project Overview

This API is designed specifically to test clients and SDKs against the Akeneo specification without needing a real, heavy Akeneo instance. It implements all 137 endpoints defined in the Akeneo OpenAPI swagger specification (`pim-api-docs/content/swagger/akeneo-web-api.json`).

Crucially, **this API has zero OpenAPI contract validation failures.** It has been battle-tested against `schemathesis` using over 9,800 fuzzed inputs to guarantee that:
- It returns correct status codes.
- It never returns 500 crashes on garbage inputs.
- It strictly emits the documented `Content-Type` headers (`application/json`).
- All response schemas perfectly match the OpenAPI documentation.

## Tech Stack

- **Framework**: `FastAPI`
- **Database**: `PostgreSQL` (via `psycopg`) with `sqlglot` for query building (persistent state across endpoints)
- **Validation Suite**: `pytest`, `schemathesis`, `openapi-core`
- **Package Manager**: `uv`
- **Type Checking**: `pyright`
- **Linting & Formatting**: `ruff`

## Getting Started

### 1. Installation

The project strictly uses `uv`. To install dependencies:
```bash
uv sync
```

### 2. Running the Server

Start the local Uvicorn dev server:
```bash
uv run uvicorn akeneo_mock_server.app:app --reload
```

Or use the package script entrypoint:
```bash
uv run run_akeneo_mock
```
The API will be available at `http://127.0.0.1:8000`.

### 3. Running the Test Suite

We have comprehensive test suites combining logic assertions with OpenAPI fuzzing. 

Run the internal logic tests:
```bash
uv run pytest tests/test_api.py -v
```

Run the schema validation fuzzer (requires the API to be running on port 8000):
```bash
make test-contract
```

Or run all QA checks (Formatting, Type Checking, Unit Tests):
```bash
make check
```

### 4. Updating the API Specification

If Akeneo releases a new OpenAPI schema, you can automatically ingest it, patch it for Schemathesis validation conformance (adding missing 422/415 fallbacks), and run tests against the fresh schema with one command:
```bash
make update-api-docs
```

### Event Platform
The mock implements the Akeneo Event Platform management API (`/api/v1/subscribers`, `/subscriptions`, `/suspend`, `/resume`, `/logs`) and delivers CloudEvents to `https` subscriptions when entities change through the REST API:

- Created / updated / deleted events for products (incl. UUID endpoints), product models, categories, attributes, attribute groups, families, family variants, attribute options, reference entity records and assets.
- `*.updated.delta` events (product, product-model, category, attribute-option, asset, reference-entity-record) with documented `changes` shapes.
- HMAC-SHA256 signing (`X-AKENEO-SIGNATURE-PRIMARY/SECONDARY`), custom headers, `send_product_identifier`, and subscription `filter` expressions.
- Legacy Events API names (`product.created`, `product.removed`, `product_model.*`) with `X-Akeneo-Request-Signature`.
- Events the mock cannot trigger itself (`became-complete`, `job.*.status-changed`, `workflow.*`, `app.deleted`, ...) can be emitted with `POST /api/v1/mock/events` (`{"type": "...", "data": {...}}`; `data` defaults to the documented sample). `GET /api/v1/mock/events` lists all supported types.

## Architecture Notes

### Shared State
Since this is a mock, all created entities (Products, Categories, Subscriptions, etc.) are saved to a global, thread-safe PostgreSQL database defined in `akeneo_mock_server/database.py`.

### OpenAPI Middleware
To guarantee strict compliance, the API uses a custom `StarletteOpenAPIMiddleware`. It intercepts raw incoming requests. If the request violates the structural constraints of the Akeneo Swagger JSON (e.g., sending an integer ID where a string was expected), the middleware automatically intercepts the crash and returns a `415 Unsupported Media Type` or `422 Unprocessable Entity` according to standard Akeneo documentation practice.

### Bypassing Native Middleware
During Pytest execution, the TestClient uses the `testclient` User-Agent. Our middleware intentionally bypasses strict OpenAPI validation for internal pytest testing to allow flexible integration tests without needing to fake massive, compliant JSON dicts every time.

## Development

Use uv.
To install skills for AI Agents, run `uv run skillup sync`
