README.md

# SSL Certificate Library

A comprehensive SSL certificate management library with Let's Encrypt ACME v2 support for Erlang/OTP applications.

## Index

- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Modules](#modules)
- [Dependencies](#dependencies)
- [Code Coverage](#code-coverage)
- [Development Commands](#development-commands)

## Features

- Full ACME v2 protocol support
- Let's Encrypt certificate automation  
- DNS and HTTP-01 challenge support
- Certificate lifecycle management
- Cryptographic operations for certificate handling
- Comprehensive validation and state management
- Modern HTTP/2 client using gun

## Installation

Add this library to your `rebar.config` dependencies:

```erlang
{deps, [
    {ssl_cert, {git, "https://github.com/permaweb/ssl_cert.git", {branch, "main"}}}
]}.
```

## Usage

### Device Configuration

Configure the SSL certificate device with the required options:

```erlang
%% Configuration for SSL certificate requests
Opts = #{
    <<"ssl_opts">> => #{
        <<"domains">> => [<<"example.com">>, <<"www.example.com">>],
        <<"email">> => <<"admin@example.com">>,
        <<"environment">> => <<"staging">>  % Use "production" for live certificates
    }
}.
```

### Certificate Request Workflow

#### Step 1: Request Certificate
```erlang
%% Initiate certificate request - returns DNS challenges
{ok, Response} = dev_ssl_cert:request(undefined, undefined, Opts),
#{<<"body">> := #{
    <<"challenges">> := Challenges,
    <<"message">> := <<"Create DNS TXT records for the following challenges, then call finalize">>
}} = Response.
```

#### Step 2: Set DNS TXT Records
Based on the returned challenges, create DNS TXT records:
```
_acme-challenge.example.com.     TXT "challenge_token_here"
_acme-challenge.www.example.com. TXT "challenge_token_here"
```

#### Step 3: Finalize Certificate
```erlang
%% After DNS records are set, finalize the certificate
{ok, FinalResponse} = dev_ssl_cert:finalize(undefined, undefined, Opts),
#{<<"body">> := #{
    <<"certificate_pem">> := CertPem,
    <<"key_pem">> := KeyPem,
    <<"domains">> := Domains
}} = FinalResponse.
```

### Certificate Management

#### Renew Certificate
```erlang
%% Renew existing certificate
RenewOpts = #{
    <<"ssl_opts">> => #{
        <<"domains">> => [<<"example.com">>, <<"www.example.com">>],
        <<"email">> => <<"admin@example.com">>,
        <<"environment">> => <<"production">>
    }
},
{ok, RenewResponse} = dev_ssl_cert:renew(undefined, undefined, RenewOpts).
```

#### Delete Certificate
```erlang
%% Delete stored certificate
DeleteOpts = #{
    <<"ssl_opts">> => #{
        <<"domains">> => [<<"example.com">>, <<"www.example.com">>]
    }
},
{ok, DeleteResponse} = dev_ssl_cert:delete(undefined, undefined, DeleteOpts).
```

### Environment Configuration

#### Staging Environment (for testing)
```erlang
StagingOpts = #{
    <<"ssl_opts">> => #{
        <<"domains">> => [<<"test.example.com">>],
        <<"email">> => <<"test@example.com">>,
        <<"environment">> => <<"staging">>
    }
}.
```

#### Production Environment
```erlang
ProductionOpts = #{
    <<"ssl_opts">> => #{
        <<"domains">> => [<<"example.com">>],
        <<"email">> => <<"admin@example.com">>,
        <<"environment">> => <<"production">>
    }
}.
```

### Direct Module Usage

For advanced use cases, you can call the underlying modules directly:

```erlang
%% Validate request parameters
{ok, ValidatedParams} = ssl_cert_validation:validate_request_params(
    [<<"example.com">>], <<"admin@example.com">>, <<"staging">>),

%% Process certificate request
{ok, ProcessResponse} = ssl_cert_ops:process_certificate_request(ValidatedParams, Wallet),

%% Validate DNS challenges
{ok, ValidationResponse} = ssl_cert_challenge:validate_dns_challenges_state(RequestState, PrivateKey),

%% Generate CSR
{ok, {CsrDer, PrivateKey}} = acme_csr:generate_csr([<<"example.com">>], #{}).
```

## Modules

- **`acme_client`** - Main ACME client API
- **`ssl_cert_ops`** - High-level certificate operations
- **`acme_protocol`** - Core ACME protocol implementation
- **`acme_crypto`** - Cryptographic operations and JWS
- **`acme_csr`** - Certificate Signing Request generation
- **`ssl_cert_challenge`** - Challenge handling and validation
- **`ssl_cert_validation`** - Certificate validation utilities
- **`ssl_cert_state`** - State management utilities
- **`ssl_utils`** - Utility functions and HTTP client

## Dependencies

- `gun` - Modern HTTP/2 client for ACME communication
- `crypto` - Cryptographic operations
- `public_key` - Public key operations
- `ssl` - SSL/TLS support
- `inets` - Additional HTTP utilities

## Code Coverage

Current test coverage across all modules:

| Module | Coverage |
|--------|----------|
| **Core Modules** | |
| `acme_client` | 25% |
| `acme_crypto` | 65% |
| `acme_csr` | 81% |
| `acme_http` | 49% |
| `acme_protocol` | 26% |
| `acme_url` | 100% |
| `ssl_cert_challenge` | 18% |
| `ssl_cert_ops` | 24% |
| `ssl_cert_state` | 65% |
| `ssl_cert_validation` | 95% |
| `ssl_utils` | 29% |
| **Test Modules** | |
| `acme_client_tests` | 91% |
| `acme_crypto_tests` | 100% |
| `acme_csr_tests` | 91% |
| `acme_http_tests` | 100% |
| `acme_protocol_tests` | 91% |
| `acme_url_tests` | 100% |
| `ssl_cert_challenge_tests` | 100% |
| `ssl_cert_integration_tests` | 100% |
| `ssl_cert_ops_tests` | 100% |
| `ssl_cert_state_tests` | 100% |
| `ssl_cert_test_suite` | 10% |
| `ssl_cert_validation_tests` | 100% |
| `ssl_utils_tests` | 100% |
| **Total Coverage** | **68%** |

### Coverage Analysis

- **High Coverage (80%+)**: `acme_csr`, `acme_url`, `ssl_cert_validation`
- **Medium Coverage (50-79%)**: `acme_crypto`, `ssl_cert_state`
- **Low Coverage (<50%)**: `acme_client`, `acme_http`, `acme_protocol`, `ssl_cert_challenge`, `ssl_cert_ops`, `ssl_utils`

## Development Commands

### Code Quality and Formatting
```bash
# Format all Erlang files
rebar3 fmt

# Check if files need formatting (don't modify)
rebar3 fmt --check

# Run linter to check code quality
rebar3 lint
```

### Testing
```bash
# Compile and run all tests
rebar3 as test eunit

# Run specific test module
rebar3 as test eunit --module=my_module_tests
```

### Code Coverage
```bash
# Run tests with coverage analysis
rebar3 cover

# Generate coverage reports
rebar3 covertool generate

# Full test and coverage workflow
rebar3 as test eunit && rebar3 cover && rebar3 covertool generate
```

### Documentation and Publishing
```bash
# Generate HTML documentation
rebar3 ex_doc

# Authenticate with Hex (one-time setup)
rebar3 hex user auth

# Publish to Hex
rebar3 hex publish
```

### Development Workflow
```bash
# Complete quality check before commit
rebar3 clean
rebar3 fmt --check
rebar3 lint
rebar3 as test compile
rebar3 as test eunit
rebar3 cover
rebar3 covertool generate
```