rust-microservice 0.1.0

A microservices framework in Rust whichs provides common functionalities for developing Web APIs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
<div align="center">

  <img alt="Rust Microservice" src="assets/rust-microservice.jpg"/>

  <h1></h1>
  <h3>Rust Microservice is a powerful framework for building web services in Rust</h3>

  ![rust](https://badgen.net/badge/Rust%20Edition/2024/red?scale=1.0)
  ![rust](https://badgen.net/badge/Rust/1.91.1/blue?scale=1.0)
  ![crate](https://badgen.net/badge/crates.io/v0.1.0/orange?scale=1.0)
  <!--[![build status](https://github.com/kenniston/rust-microservice/actions/workflows/rust.yml/badge.svg)](https://github.com/kenniston/rust-microservice/actions/workflows/rust.yml)-->
  [![GitHub stars](https://img.shields.io/github/stars/kenniston/rust-microservice.svg?style=social&label=Star&maxAge=1)](https://github.com/kenniston/rust-microservice/)
  <br>Support us with a ⭐ !

</div>


# πŸ“¦ Rust Microservice Framework <!-- omit from toc -->

A Rust crate whichs provides a framework for building microservices. It follows the MVC 
(Model-View-Controller) architecture pattern and provides a strong focus on high performance, 
security, and scalability.

## πŸ“‹ Table of Contents <!-- omit from toc -->

- [πŸ“– Overview]#-overview
- [✨ Features]#-features
- [πŸ› οΈ Installation]#️-installation
- [⚑ Quick Start]#-quick-start
- [πŸ’‘ Usage Examples]#-usage-examples
  - [πŸ–₯️ Simple Server]#️-simple-server
  - [πŸ”— ServerApi Macro]#-serverapi-macro
  - [πŸ›’οΈ Database Macro]#️-database-macro
  - [πŸ” Secured Macro]#-secured-macro
  - [Attribute Reference]#attribute-reference
    - [**`method`**]#method
    - [**`path`**]#path
    - [**`authorize`**]#authorize
  - [Examples]#examples
    - [**`Single role`**]#single-role
    - [**`Any role`**]#any-role
    - [**`All roles`**]#all-roles
- [YAML-based server configuration file]#yaml-based-server-configuration-file
  - [Server]#server
  - [CORS]#cors
  - [Security β€” OAuth2 / OpenID Connect]#security--oauth2--openid-connect
  - [OAuth2 Client]#oauth2-client
  - [JWKS]#jwks
  - [Data Sources]#data-sources
  - [*Redis*]#redis
  - [*Relational Databases*]#relational-databases
  - [*BigQuery Database Connection*]#bigquery-database-connection
  - [Metrics]#metrics
  - [Runtime Notes]#runtime-notes
- [πŸ”§ Development Setup]#-development-setup
- [πŸ”¬ Test Environment Infrastructure]#-test-environment-infrastructure
  - [Architecture Overview]#architecture-overview
  - [Blocking Execution Helper]#blocking-execution-helper
  - [Container Utilities]#container-utilities
    - [Supported Services]#supported-services
  - [Usage]#usage
  - [Concurrency Model]#concurrency-model
  - [Safety Guarantees]#safety-guarantees
- [πŸ“¦ Project Dependencies]#-project-dependencies
- [πŸ“„ License]#-license
- [🀝 Contributing]#-contributing
- [πŸ“ Changelog]#-changelog


## πŸ“– Overview

The framework is designed to be modular, allowing developers to register their own route 
handlers, serializers, and business logic. This enables a high degree of customization and 
flexibility, making it suitable for a wide range of use cases.

## ✨ Features

- Modular architecture with support for registering custom route handlers, serializers, 
  and business logic;
- High performance HTTP server with support for asynchronous request handling;
- Strong focus on security and scalability;
- Support for JSON and XML serialization/deserialization;
- Built-in metrics export compatible with Prometheus;
- YAML-based configuration via `config.yaml`;
- Built-in API documentation with OpenAPI and interactive UI through Swagger UI powered 
  by Utoipa Swagger UI;
- Built-in Health Check endpoint;
- Configurable server and actuator ports (defaults: `8080` and `7188`);
- Native CORS configuration support;
- MVC-based project architecture;
- Automatic database connectivity (SQLite, PostgreSQL, MySQL, and Google BigQuery) driven 
  by YAML configuration;
- Local development and integration testing with Docker Compose and Testcontainers;
- Integration test wrapper for initializing a global Testcontainers environment;
- Built-in integration with OAuth2 servers (Keycloak on the server example);
- Automatic discovery URL resolution for:
  issuer, jwks, token, authorization, introspection, user-info, and end-session endpoints;
- Endpoint-level security configuration using Rust macros.
  
## πŸ› οΈ Installation

Add the Rust Microservice to Cargo.toml:

```toml

[dependencies]
rust-microservice = "0.1.0"

```

> The `Rust Microservice` framework relies on several core crates to bootstrap and run projects.  
> As a result, the following dependencies are required in any application built with the framework:
>
> - `actix-web`
> - `tokio`
> - `utoipa`
> - `sea-orm`
> - `utoipa-swagger-ui`

## ⚑ Quick Start

To configure the server, apply the ServerApi macro to the main function. The macro automatically
discovers all actix-web handlers defined in the `controllers_path` ([ServerApi Attributes](#serverapi-macro)) 
attribute and initializes the databases specified in the YAML configuration file.

The configuration file can be provided to the framework using the `--config-file` command-line 
parameter (or the `CONFIG_FILE` environment variable), or as a Base64-encoded file via the 
`--b64-config-file` parameter (or the `B64_CONFIG_FILE` environment variable).

```rust
use rust_microservice::ServerApi;

#[ServerApi]
fn main() -> rust_microservice::Result<(), String> {}

```

## πŸ’‘ Usage Examples

### πŸ–₯️ Simple Server

The Rust Microservice framework has a default config wich starts a simple server on port `8080`.
This server also enable a health check and monitoring feature. The health check can be reach
on default port `7188` and `/health` endpoint.

Default server configuration:

```yaml
server:
  host: "0.0.0.0"
  port: 8080
  health-check-port: 7188
```
---

### πŸ”— ServerApi Macro

The `ServerApi` macro is a procedural macro that generates the code necessary to
start an `actix-web` HTTP server with support for OpenAPI documentation and
a health check endpoint.

The `ServerApi` macro takes the following attributes:

- `controllers_path`: A comma-separated list of paths to modules containing
  controllers. The macro will recursively traverse the directories and generate
  code to register the controllers with the HTTP server.

- `openapi_title`: A string used as the title of the OpenAPI documentation.

- `openapi_api_description`: A string used as the description of the OpenAPI
  documentation.

- `database`: A boolean indicating whether the microservice should enable database
  integration. If set to `true`, the macro will generate code to initialize the
  database connection pool using the `sea_orm` crate.

- `banner`: A string used as the banner of the microservice. The banner is displayed
  in the server logs during startup.

Example of a minimal server bootstrap using this crate:

```rust
use rust_microservice::ServerApi;

#[ServerApi(
    controllers_path = "src/module, src/controllers",
    openapi_title = "🌐 Rest API Server",
    openapi_api_description = "Rest API OpenApi Documentation built with Rust πŸ¦€.",
    database = "true",
    banner = r#"
            _~^~^~_         ___    ___   ____    ____
        \) /  o o  \ (/    / _ |  / _ \ /  _/   / __/___  ____ _  __ ___  ____
          '_   -   _'     / __ | / ___/_/ /    _\ \ / -_)/ __/| |/ //! -_)/ __/
          / '-----' \    /_/ |_|/_/   /___/   /___/ \__//!_/   |___/ \__//!_/
    "#
)]
async fn start_server() -> rust_microservice::Result<(), String> {}
```
---

### πŸ›’οΈ Database Macro

The `database` macro is a procedural macro that injects a database connection
into repository methods.

It expects two mandatory attributes:
- `name`: selects which configured database connection will be used.
- `error`: defines the error variant returned when the database is not configured or
  database connection cannot be found.

The macro injects a variable named `db` with type `&DatabaseConnection` (seaorm),
so the function body can execute queries directly.

Example:

```rust
use rust_microservice::{Server, database};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum UserError {
    #[error("Database is not configured")]
    DatabaseNotConfigured,

    #[error("User not found")]
    NotFound,
}

pub type Result<T, E = UserError> = std::result::Result<T, E>;

#[database(name = "api", error = "UserError::DatabaseNotConfigured")]
pub async fn get_user_by_id(user_id: i32) -> Result<()> {
    user::Entity::find_by_id(user_id)
       .one(&db)
       .await
       .map_err(|_| UserError::NotFound)?
       .ok_or(UserError::NotFound)
       .map(Into::into)
}
```
---

### πŸ” Secured Macro

The `Secured` macro protects `actix-web` endpoints by attaching an authentication middleware.

When applied to an endpoint, it validates:

- JWT presence in the request.
- JWT signature.
- JWT expiration time (`exp` claim).
- JWT issuer (`iss` claim).
- Required roles from the `authorize` expression.

### Attribute Reference

Macro usage format:

```rust
#[secured(method = "...", path = "...", authorize = "...")]
```

#### **`method`**

Defines the HTTP method used to map the endpoint in Actix-Web.

Supported values: 

- `get`
- `post`
- `put`
- `delete`
- `head`
- `connect`
- `options`
- `trace`
- `patch`

#### **`path`**

Defines the endpoint path to be registered by Actix-Web.

Example:

```rust
path = "/v1/user/{id}"
```

#### **`authorize`**

Defines the required role rule that must be satisfied by roles present in the JWT.

Supported formats:

1. `Single role`: validates one role in the token.

```rust
authorize = "ROLE_ADMIN"
```

2. `hasAnyRole`: validates that at least one role in the list exists in the token.

```rust
authorize = "hasAnyRole(ROLE_ADMIN, ROLE_USER)"
```

3. `hasAllRoles`: validates that all roles in the list exist in the token.

```rust
authorize = "hasAllRoles(ROLE_ADMIN, ROLE_USER)"
```

### Examples

#### **`Single role`**

```rust
#[secured(method = "post", path = "/v1/user", authorize = "ROLE_ADMIN")]
pub async fn create_user_endpoint(...) -> HttpResponse {
    // handler body
}
```

#### **`Any role`**

```rust
#[secured(
    method = "get",
    path = "/v1/user/{id}",
    authorize = "hasAnyRole(ROLE_ADMIN, ROLE_USER)"
)]
pub async fn get_user_endpoint(...) -> HttpResponse {
    // handler body
}
```

#### **`All roles`**

```rust
#[secured(
    method = "delete",
    path = "/v1/user/{id}",
    authorize = "hasAllRoles(ROLE_ADMIN, ROLE_AUDITOR)"
)]
pub async fn delete_user_endpoint(...) -> HttpResponse {
    // handler body
}
```


## YAML-based server configuration file
The server behavior is fully driven by a YAML configuration file. This file defines network 
settings, security providers, data sources, and observability integrations used at runtime.

The configuration is loaded during application startup and applied automatically by the framework.

### Server

Defines how the HTTP service is exposed and how it interacts with the runtime environment.

| Field                 | Description                                                               |
| --------------------- | ------------------------------------------------------------------------- |
| `host`                | Network interface where the server binds.                                 |
| `port`                | Main HTTP port used by the API.                                           |
| `health-check-port`   | Dedicated port exposing the health endpoint.                              |
| `use-docker-compose`  | Enables orchestration of dependencies via Docker Compose.                 |
| `docker-compose-file` | Path to the Docker Compose definition used when orchestration is enabled. |

### CORS

Controls cross-origin access policies.

| Field                     | Description                                                        |
| ------------------------- | ------------------------------------------------------------------ |
| `max-age`                 | Duration (seconds) browsers cache preflight responses.             |
| `allow-credentials`       | Allows cookies and authorization headers in cross-origin requests. |
| `allowed-methods`         | HTTP methods allowed for cross-origin calls.                       |
| `allowed-headers`         | Headers accepted from clients.                                     |
| `allowed-origins_pattern` | Comma-separated list of allowed origin patterns.                   |

### Security β€” OAuth2 / OpenID Connect

Enables authentication and token validation using an OAuth2 provider.

| Field                     | Description                                                        |
| ------------------------- | ------------------------------------------------------------------ |
| `enabled`                 | Activates OAuth2 protection for secured endpoints.                 |
| `load-from-discovery-url` | Automatically loads provider metadata from the discovery endpoint. |
| `discovery-url`           | OpenID Provider discovery document.                                |
| `issuer-uri`              | Expected token issuer identifier.                                  |
| `jwks-uri`                | JSON Web Key Set endpoint used to validate tokens.                 |
| `token-uri`               | Endpoint for obtaining access tokens.                              |
| `authorization-uri`       | Authorization endpoint for login flows.                            |
| `introspection-uri`       | Endpoint for validating opaque tokens.                             |
| `user_info-uri`           | Endpoint returning authenticated user claims.                      |
| `end_session-uri`         | Logout endpoint for session termination.                           |

### OAuth2 Client

Credentials used by the server when interacting with the identity provider.

| Field    | Description                             |
| -------- | --------------------------------------- |
| `id`     | OAuth2 client identifier.               |
| `secret` | OAuth2 client secret.                   |
| `scope`  | Requested scopes during authentication. |


### JWKS

Defines local JSON Web Keys used for token signing or validation.

Each key entry contains:

- kid β€” Key identifier
- kty β€” Key type
- alg β€” Signing algorithm
- use β€” Key usage
- e β€” Public exponent
- n β€” RSA modulus
- x5c β€” X.509 certificate chain

This section is typically used when keys are managed internally or cached locally.

### Data Sources

### *Redis*

Configuration for distributed cache and key-value storage.

| Field                  | Description                                     |
| ---------------------- | ----------------------------------------------- |
| `enabled`              | Enables Redis integration.                      |
| `host` / `port`        | Connection settings.                            |
| `client-type`          | Redis client implementation.                    |
| `lettuce.pool`         | Connection pool configuration.                  |
| `repositories.enabled` | Enables repository abstraction backed by Redis. |


### *Relational Databases*

Defines a list of database connections used by the application.

Each database entry supports:

- Connection pooling configuration
- Timeouts and lifecycle settings
- SQL logging control
- Independent enable/disable toggle

This allows multiple data sources (e.g., API DB, job processing DB) to coexist in the same runtime.

| Field            | Description                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------------- |
| `name`           | Logical name of the database connection used by the server.                                       |
| `enabled`        | Enables or disables this database configuration. When `false`, the connection is not initialized. |
| `url`            | Database connection string used to establish the connection.                                      |
| `min-pool-size`  | Minimum number of connections maintained in the pool.                                             |
| `max-pool-size`  | Maximum number of connections allowed in the pool.                                                |
| `logging`        | Enables query and connection logging for this database.                                           |
| `aquire-timeout` | Maximum time (in seconds) to wait when acquiring a connection from the pool.                      |
| `max-lifetime`   | Maximum lifetime (in minutes) of                                                                  |

> Important: The framework currently supports only SQLite, PostgreSQL, MySQL, MariaDB, and 
> Microsoft SQL Server databases.

### *BigQuery Database Connection*

This section defines the configuration parameters required to establish a secure connection
to Google BigQuery, the fully managed data warehouse provided by Google. These settings allow
the server to authenticate, select the target project and dataset, and control execution
behavior for queries. .

| Field          | Description                                 |
| -------------- | ------------------------------------------- |
| `enabled`      | Enables BigQuery access.                    |
| `print-tables` | Logs available tables during startup.       |
| `region`       | Dataset region.                             |
| `project`      | Google Cloud project identifier.            |
| `credential`   | Base64-encoded service account credentials. |
| `dataset`      | List of datasets used by the application.   |


### Metrics

Controls application observability and monitoring integration.

| Field      | Description                             |
| ---------- | --------------------------------------- |
| `enabled`  | Enables metrics collection.             |
| `app-name` | Identifier used when exporting metrics. |


### Runtime Notes

- Disabled components remain configured but inactive.
- Secrets should be externalized in production environments.
- Configuration values can be overridden via environment variables or CLI parameters.
- The configuration is validated during server startup.

## πŸ”§ Development Setup

```bash
# Clone the repository
git clone https://github.com/kenniston/rust-microservice
cd rust-microservice

# Build the server example
cargo build -p server

# Run the server example
cargo run -p server

# Format code
cargo fmt

# Check for issues
cargo clippy
```

## πŸ”¬ Test Environment Infrastructure

The framework provides utilities for bootstrapping and managing an isolated
integration test environment powered by Docker containers and an async
server runtime.

It is designed to:

- Provision and manage test containers (e.g., Postgres, Keycloak);
- Coordinate initialization and shutdown across threads;
- Provide global access to running containers;
- Ensure deterministic teardown after tests complete.

The module is intended for integration and end-to-end testing scenarios
where external dependencies must be provisioned dynamically.

### Architecture Overview

The test environment follows a controlled lifecycle with three main phases:

1. **Setup Phase**
  - Initializes logging
  - Starts required containers
  - Executes optional post-initialization tasks
  - Signals readiness to the test runtime

2. **Execution Phase**
  - Tests run against the live server and provisioned services
  - Containers remain active and globally accessible

3. **Teardown Phase**
  - Receives shutdown signal
  - Stops and removes all registered containers
  - Releases global resources

Synchronization between phases is handled using global channels and locks.

### Blocking Execution Helper

The module provides an internal utility for executing async code from
synchronous contexts by creating a dedicated Tokio runtime. This is used
primarily during container shutdown and cleanup.

---

### Container Utilities

The `containers` submodule provides helpers for starting commonly used
infrastructure services.

#### Supported Services

- **Postgres**
  Starts a database container with optional initialization scripts,
  network configuration, and credentials.

- **Keycloak**
  Starts an identity provider container with realm import support and
  readiness checks.

Each container:

- Waits for readiness before returning
- Registers itself for automatic teardown
- Returns a connection URI for test usage

---

### Usage

```rust
#[ctor::ctor]
pub fn setup() {
    rust_microservice::test::setup(
        async || {
            let mut settings = load_test_settings();

            let mut containers: Vec<Box<dyn Any + Send>> = vec![];

            let postgres = start_postgres_container(&mut settings).await;
            if let Ok(postgres) = postgres {
                containers.push(Box::new(postgres.0));
            }

            let keycloak = start_keycloak_container(&mut settings).await;
            if let Ok(keycloak) = keycloak {
                containers.push(Box::new(keycloak.0));
            }

            (containers, settings)
        },
        || async {
            info!("Getting authorization token ...");
            let oauth2_token = get_auth_token().await.unwrap_or("".to_string());
            TOKEN.set(oauth2_token);
            info!("Authorization token: {}...", token()[..50].bright_blue());
        },
    );
}
 ```

Teardown is handled automatically by the `dtor` attribute.
```rust
#[ctor::dtor]
pub fn teardown() {
    rust_microservice::test::teardown();
}
```


### Concurrency Model

The environment runs inside a dedicated multi-thread Tokio runtime
spawned in a background thread. This allows synchronous test code to
coordinate with async infrastructure without requiring async test
functions.

Communication is performed via channels that coordinate:

- Initialization completion
- Container stop commands
- Shutdown confirmation


### Safety Guarantees

- Containers remain alive for the full test lifecycle
- Teardown is deterministic and blocking
- Global state is initialized exactly once
- Async resources are properly awaited before shutdown

>The environment assumes Docker is available and reachable using default
>configuration. Failure to connect to the Docker daemon will cause setup
>to abort.

>All containers are forcefully removed during teardown to ensure a clean
>test environment for subsequent runs.


## πŸ“¦ Project Dependencies

This section describes the common dependencies used by projects built with the Rust 
Microservice Framework. These libraries provide the foundation for web handling, 
serialization, asynchronous execution, database access, observability, and API 
documentation.

The dependencies listed below represent a typical setup and may be adjusted according 
to project requirements.

- `rust-microservice` – Core framework providing the microservice structure and shared components.
- `rust-embed` – Embeds static assets directly into the binary.
- `actix-web` – High-performance asynchronous web framework.
- `serde` – Serialization and deserialization framework.
- `serde_json` – JSON support for Serde.
- `tokio` – Asynchronous runtime for non-blocking operations.
- `sea-orm` – Async and dynamic ORM for database access.
- `utoipa` – OpenAPI specification generation.
- `utoipa-swagger-ui` *(actix-web feature)* – Embedded Swagger UI for API exploration.
- `google-cloud-bigquery` – Client library for Google BigQuery integration.
- `base64` – Base64 encoding and decoding utilities.
- `tracing` – Structured, event-based logging and diagnostics.
- `thiserror` – Ergonomic error definitions.
- `derive_more` – Additional derive macros to reduce boilerplate.
- `colored` – Colored terminal output.
- `env_logger` – Environment-based logger implementation.
- `log` *(serde feature)* – Logging facade with serialization support.
- `reqwest` – HTTP client for outbound requests.
- `reqwest-tracing` *(optional)* – Tracing instrumentation for HTTP client requests.
- `reqwest-middleware` *(optional)* – Middleware support for Reqwest clients.


## πŸ“„ License
  
Licensed under either of

- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.


## 🀝 Contributing

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

Contributions are welcome! Join us β€” let’s build the future of Rust together.

Here's how to get started:

1. **🍴 Fork** the repository
2. **πŸ”§ Create** a feature branch (`git checkout -b feature/amazing-feature`)
3. **πŸ’Ύ Commit** your changes (`git commit -m 'Add amazing feature'`)
4. **πŸ“€ Push** to the branch (`git push origin feature/amazing-feature`)
5. **πŸ”€ Open** a Pull Request


## πŸ“ Changelog
  
  πŸ‘‰ See [CHANGELOG.md](CHANGELOG.md) for version history and updates.