---
title: Charmhub | tls-certificates interface
description: Interfaces describe the relation between two charms. This interface shows
  opinionated, standardized interface specifications for charm relations.
url: https://charmhub.io/integrations/tls-certificates
---

# tls-certificates

Version 1, published

## Usage

This relation interface describes the expected behavior of any charm claiming to be able to provide
or consume TLS certificates.

The recommended approach is to use [charmlibs.interfaces.tls\_certificates](https://pypi.org/project/charmlibs-interfaces-tls-certificates).

## Direction

As with all Juju relations, the `tls-certificates` interface consists of a provider and a requirer.
One of these, in this case the `provider`, will be expected to create TLS certificates where the
`requirer` will be able to consume and use them for TLS communications.

```
flowchart
    Requirer -- certificate_signing_requests --> Provider
    Provider -- certificates --> Requirer
```

## Behavior

Both the requirer and the provider need to adhere to a certain set of criteria to be considered
compatible with the interface.

### Requirer

* Is expected to generate (or use an existing) private-key
* Is expected to provide a list of CSR's for which it requires certificates
* Is expected to specify whether the certificate request is for a Certificate Authority (CA) or not
* Is expected to use the appropriate databag depending on whether the Certificate is meant to be used by the unit or by the application.
* Is expected to stop using a certificate when revoked by the Provider

### Provider

* Is expected to provide its CA certificate for each successfully processed CSR
* Is expected to provide its CA chain for each successfully processed CSR
* Is expected to provide a certificate for each successfully processed CSR
* Is expected to provide an error in `request_errors` for each CSR that could not be processed
* Is expected to ensure mutual exclusivity: a CSR appears in **either** `certificates` or `request_errors`, never both
* Is expected to overwrite the existing certificates and/or remove the pre-existing certificates from the relation data.
* May optionally advertise its certificate issuing capabilities in `capabilities` (best-effort). This field is additive and optional; legacy providers and requirers that ignore it are unaffected.

## Relation Data

[[Pydantic Schema]](https://github.com/canonical/charmlibs/blob/main/interfaces/tls-certificates/interface/vv1/schema.py)

### Requirer

The requirer specifies a set of certificate signing requests (CSR's).

#### Example

```
{
  "unit-data": {
    "certificate_signing_requests": "..."
  }
}
```

Where `certificate_signing_requests` is a stringified `json` array of objects like:

```
[
  {
    "certificate_signing_request": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2FUQ0NBVkVDQVFBd0pERUxNQWtHQTFVRUJoTUNWVk14RlRBVEJnTlZCQU1NRENvdVltRnVZVzVoTG1OdgpiVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNaDQxVkdjajJ1c2F1L3R6amd3CkVCcEoxM3lCWDYvQUZjL25Na1R4VTYxT2JycldkVjkwQlcwbS9ZVWdxN0VRNWR3UkJIOFB3L3ZFN3NaN0FoVk0KOENncllKTzQxYWxmRTlFcjU2aFNxSlVpeFV2VXNtWUppcUtwTVpjT3QzSW14cnNHRkh2MXBoN0NoL3R1bCtXNgpNY3RXZnYrNWIreGhEYWZMcC8rMUZSQWhYTHlqZkd0ZCsrUTJISzV6ZS9qQUN4YzF3a3pFNmpwTkxwNHJGL1h5CjFKVXdkZDVYVURkWjVmL1JrWWNKaEJ2OHpWbjd0WEYvZ0FOVDc2bHI4ZS82VWZHK0FQUURvL1UrMUdpeG4yL0sKdHVnYVBNRFlBZ2xLYm9JQVh3em9HbEpIR1crcEZZTGU2eGhHTE15RWhCRmJ0a1BKNGRDS0l5Tnh1T29rSHp3Ygp5aDhDQXdFQUFhQUFNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNZa0g1aVNhT0dGSnREWHhCd0xRNldxc0JhCnU3VkxhMHJubksrbCtmUjNwV2Q5UThqOG5PTXI4d2szb2FNQ2JFQ3RaSitqYjZEN2Y0aS9IN1BOOElOVzl6S0IKVjltVTh0YnhhRTdub2x0UW9XQTgwU3hSN3BhWWF3Tit0NnNWUTN3aTJyZ3F2aGpGVEJKQStiYmZsQjZRM3FzYgpOSDAwYUo3eTdrU1d1MWxxNkhERnh4L0FlMEZLVUNqQVNrWnhsU0taUEJYcWF1UG9tU3hCMVhGN1pWN244eGtOCjNIcU1UdnhiUDR5bU1RQ1hxaktzN2hBQUVmK0I3UjNHYzdmbnhQRDNMMGREU3dGanJXL2tvZy8wSTRNa1RiaGUKT29FRGdpT09UQmlHaDcvZ3RXTXVXcHBmYys0ckloR1FEMGRLR1NpUVFjL2tPMlExZmNyME1YM0Z0dnUwCi0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo="
  },
  {
    "certificate_signing_request": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2FEQ0NBVkFDQVFBd0l6RUxNQWtHQTFVRUJoTUNWVk14RkRBU0JnTlZCQU1NQ3lvdVltRnVZVzVoTG1OaApNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXNKRFFiY0IxZVNwYjRjUmpEZXNWCm1lbmMvT0ZXMEZrcUQ3aUtDVVZmakFjSjdVOGowTTZmZC9FL3o1OFRrY0htQmRqbGlqcitoTStmVWRKMXhpQ3gKanlEMTkwZjU0N2s1RmZkYUFkcFhkaHpQZVJmVWt5MFlwTUY0M1BPVnc3MXhCQm8wQXgvK1RGNE9zd2tBa1J3egpFQVhpZkZTdlhPcUFnNG9BVG9MbVYrclh4cmFidFlBM1VFcGxxRTc2ZVdCdVdJbWpGZ2IzbDVWb25Sc1pPUXE1CjlVNE1aSzhoMi9LeEVqMUpGcFpSNnJteDdiUEZxOUNzbjhYb1V2MlRoRFBvNlNWRXJxUWxSdGNXVVFGSG9Ic2UKK0JUUmI5Q255WW5hdFF5YThaU0Y3QnZ4RFIrY0hyV04vNHhIeW1YdkU2VDJ4STFSN3pqQkZvQ3hISEVaY3MwTgowUUlEQVFBQm9BQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSmNlTTY2SnpwaFVwZm9NY1VNd3NhYU1YczVQCjFEQTFnYkMzOE9sZEkrU2NtMkJxeWlkVmNRVXBaclhBSTdhdUJ1ZzVQUlJmcEpVSWZKSExxYlUraTJJODRwQlAKOG4xR0RKeTg0dGllM2RaVlcvakhzVGQ4QVpNTGJVZkFPZUgxREVWRzdFK0dXWlRtd25UZnJKZnNNSy9mN3Y0YwpxemdsTGpBd29Cbjl5QWhvdVBpU1JZY0Vhdng2bzhVbFpLZFBuQ0tzb240WGV5RUh1cjUwLzlmS05sWlhRMENvCndmQ3E2MzJkQ2Q2L0VyRkpOQTVEemRzVnp3aDZiWXJIU3R0UlFMN012NThpaEEzeVBwN3dUYVg3UTBxK1hvZTEKYksvU1gvT3U3V1pGUXFzZy8raENHZHBxL3NUYy9RaGRBcjNaMTk1NmpiS2k5bjg2d2FzZTdwYjhGcGc9Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=",
    "ca": true
  }
]
```

### Provider

The provider charm responds to CSRs submitted by the requirer:

* **Success case**: For each successfully processed CSR, the provider replies with a certificate, a CA certificate, and a CA chain in the `certificates` array.
* **Failure case**: For each CSR that cannot be processed, the provider **should** reply with an error in the `request_errors` array, explaining why the request failed. This allows requirers to understand why a certificate was not issued.

**Important**: For each CSR, the provider will include **either** a certificate in the `certificates` array **or** an error in the `request_errors` array, but never both. A given CSR will appear in only one of these arrays.

**Backward Compatibility**:
The `request_errors` field is optional and additive. Older requirers that do not understand this field will continue to function normally, they will simply not receive error information for failed requests.
Older providers that don't support `request_errors` will simply not include failed CSRs in any response.

#### Example

```
{
  "application-data": {
    "certificates": "...",
    "request_errors": "..."
  }
}
```

Where `certificates` is a stringified `json` array of objects like this:

```
[
  {
    "ca": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNVENDQWhtZ0F3SUJBZ0lVRWg5dWl3Q0tQVXRLaTY3bFd6aFk1ckJoS1dFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0tERUxNQWtHQTFVRUJoTUNWVk14R1RBWEJnTlZCQU1NRUhKdmIzUmpZUzV3YVhwNllTNWpiMjB3SGhjTgpNakl3TnpJME1UY3lOVE15V2hjTk16SXdOekl4TVRjeU5UTXlXakFvTVFzd0NRWURWUVFHRXdKVlV6RVpNQmNHCkExVUVBd3dRY205dmRHTmhMbkJwZW5waExtTnZiVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0MKQVFvQ2dnRUJBSTJ3MGlVbUVrcTR6aWpaNllIcEtmQ1NhaGZuQjZMVTR6SW9YWFhnck9mRzNORkxuMlVpckQ3NgovNzdPSU9SR0k5TGk3czlScEQwZ21hY3lNK0o1S2RBbCsxUzJpWFRLSEhsWU9jd0EzZUZ3V0ZtTFBGY1poSjVJCjQ5b3BhL1NyVXkrMFFsbFlKUTdVSGdNNm1BSncyRUxtd3FPMlJsRGsvWnBDaTdieEtoR2VmcDR6K1l3dGNxVDMKMWduSzBEaE1yNVlYRHNHaDBPVWhjaWdjYmxBRW43bHBYdTREQThDSHpkdTZ5SlRuTmZXSXVSNXRwTHN5WFB3QgpWNzBORmQ0SnV6dW45L2tRZ2s0cmJtYWJYWi9wdzVPZ1NnMzVCTzNlRlU4RkxoM2dpTFRqQXJQOUx2M1hMN0NXCmE4MXMvZkpKK2xaRUs0aEVoUVlSMUc2UDMxRS9mWUVDQXdFQUFhTlRNRkV3SFFZRFZSME9CQllFRko4Qk10MUcKY1QvY1M5QVNFVEgvbW1pRzNhOWJNQjhHQTFVZEl3UVlNQmFBRko4Qk10MUdjVC9jUzlBU0VUSC9tbWlHM2E5YgpNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQXlERWdpUzIzaUMxM3RwCmtTMFlXOXMyNlk2RnJ4T2FMYVE0RWpPTXE2MkR5aGhKL1lKVjhlbExLd0RGd2NzSXVpMGN4eDBBT3V2TnAxaTQKNUJWYnIvMzN3SlQ5bVBSaklPK2FOWUtQSk9VNmw3UzV5MDBCb0FTekZoaGdVR1Q3aGhTK0crU2ZiTVZ1dUlxUgo1MU9RLzNsOFFBUzVKaWp5akN6cGdwY2tKVldoOUdiV2lYdkFwczMwb3dHdGh1Umpkd1NQUVY2V284eE13M3FkCmF0bDV2ekd0WkVqeG5hRzhtK1ppVkdUbVg4MWtUeVJQN0hlTndRZ3NMSUNQVzQyUThIVnNOL2g3VmVRTVVIdWcKenFrMFpTdWM5aDlpZ3dwc1lDNndpQUoyckxEOE8wRkZYNkV6elZmQlZEbjUxQW9WRklRS256UU1udDF6T1g0YgpPWjV4MStNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "chain": [
      "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNVENDQWhtZ0F3SUJBZ0lVRWg5dWl3Q0tQVXRLaTY3bFd6aFk1ckJoS1dFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0tERUxNQWtHQTFVRUJoTUNWVk14R1RBWEJnTlZCQU1NRUhKdmIzUmpZUzV3YVhwNllTNWpiMjB3SGhjTgpNakl3TnpJME1UY3lOVE15V2hjTk16SXdOekl4TVRjeU5UTXlXakFvTVFzd0NRWURWUVFHRXdKVlV6RVpNQmNHCkExVUVBd3dRY205dmRHTmhMbkJwZW5waExtTnZiVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0MKQVFvQ2dnRUJBSTJ3MGlVbUVrcTR6aWpaNllIcEtmQ1NhaGZuQjZMVTR6SW9YWFhnck9mRzNORkxuMlVpckQ3NgovNzdPSU9SR0k5TGk3czlScEQwZ21hY3lNK0o1S2RBbCsxUzJpWFRLSEhsWU9jd0EzZUZ3V0ZtTFBGY1poSjVJCjQ5b3BhL1NyVXkrMFFsbFlKUTdVSGdNNm1BSncyRUxtd3FPMlJsRGsvWnBDaTdieEtoR2VmcDR6K1l3dGNxVDMKMWduSzBEaE1yNVlYRHNHaDBPVWhjaWdjYmxBRW43bHBYdTREQThDSHpkdTZ5SlRuTmZXSXVSNXRwTHN5WFB3QgpWNzBORmQ0SnV6dW45L2tRZ2s0cmJtYWJYWi9wdzVPZ1NnMzVCTzNlRlU4RkxoM2dpTFRqQXJQOUx2M1hMN0NXCmE4MXMvZkpKK2xaRUs0aEVoUVlSMUc2UDMxRS9mWUVDQXdFQUFhTlRNRkV3SFFZRFZSME9CQllFRko4Qk10MUcKY1QvY1M5QVNFVEgvbW1pRzNhOWJNQjhHQTFVZEl3UVlNQmFBRko4Qk10MUdjVC9jUzlBU0VUSC9tbWlHM2E5YgpNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQXlERWdpUzIzaUMxM3RwCmtTMFlXOXMyNlk2RnJ4T2FMYVE0RWpPTXE2MkR5aGhKL1lKVjhlbExLd0RGd2NzSXVpMGN4eDBBT3V2TnAxaTQKNUJWYnIvMzN3SlQ5bVBSaklPK2FOWUtQSk9VNmw3UzV5MDBCb0FTekZoaGdVR1Q3aGhTK0crU2ZiTVZ1dUlxUgo1MU9RLzNsOFFBUzVKaWp5akN6cGdwY2tKVldoOUdiV2lYdkFwczMwb3dHdGh1Umpkd1NQUVY2V284eE13M3FkCmF0bDV2ekd0WkVqeG5hRzhtK1ppVkdUbVg4MWtUeVJQN0hlTndRZ3NMSUNQVzQyUThIVnNOL2g3VmVRTVVIdWcKenFrMFpTdWM5aDlpZ3dwc1lDNndpQUoyckxEOE8wRkZYNkV6elZmQlZEbjUxQW9WRklRS256UU1udDF6T1g0YgpPWjV4MStNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
    ],
    "certificate_signing_request": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2FEQ0NBVkFDQVFBd0l6RUxNQWtHQTFVRUJoTUNWVk14RkRBU0JnTlZCQU1NQ3lvdWNHbDZlbUV1WTI5dApNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTJNTkVqM2VNelp3Y2NzbE1ld1JDClE1bTdVYko5dDBrUFlhcmNlb0JmOUlyT2Rkd2F1Z012TCtHcnlaMjdMOGE3b2JDMVlHeVV5Uzh4YUpBYkxSamMKY1RDYTJrV2NVMUJ1NnRrTGtyVmhpc1ZHTWNKT3FBek1lRWdrczRQTTU2RndNdFFaSUxKblFDNGd4c21rMnVQTgpMeXpMOFA5MUFZN2twaitLaUVyVEF1cy9PYzZMRW9WcW5pRklZMzZscTlSckdDL1IzOGNqVWRQRnZjU3hGRmYwCmVuSFJtYkNkd1J6ZmZQYzVoT2YwUFl2cCtuKzVQWGcyYjZjRlFvV0FaQTYvQjhTS3IvZmxRTmFEd3cwb2E3WHQKdjlUZSsrNzY2UHB0dDkwU1JVSXRta3FFNkZiaWdqZVlmWUVEWVRPRWwweU9DbzNEUlZUcVptNjFsSFBoUzU4VApnUUlEQVFBQm9BQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRXR4M1BJb2ozRko1VG41czZhU1NobHcwL3VSCkxKQkxYUCtSZUNRNkxTT3NabWpiUE1QVHo2ZVpKejR3cko1Zy9yRmJBeGp1VW03T2pWTUwzNDdkNzNteERVM2cKaENFd1NGN1NMSllwbUl6MnRPNTB1YmdDVFM5UnBZdDNWMkU4TEhVY3piVUhXQmRCUDE1TElTZVRQZWxvRlFIUgppb3I4VElQSHV1N0JGK3dwYlovdVZ0SE5TOUE3K2tlbmtHNjhlN2NJakNTZFl5Q0NaTnZLUkZLYU1IT3dHVWNICkpDZmNmbkErOGo5VUh6S0NTOWNIZjRhQmpBMm9QZ0lVanZCWlNRd0hlQnYzOFVFdXg5VmJRdXdHVHZEYlo3R3QKSFh5RnJRUWRBNW80RmFjMWNCMVhwc2JmbDZXRXNaSUNwOXF0Rmtsb1ZqK3FzbytBY2o0ZFZxQ0hjazg9Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=",
    "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURmekNDQW1lZ0F3SUJBZ0lVTWJRVk1uK3JOVjlOUjlCQ1pRRE9CZkg5NkJVd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0tERUxNQWtHQTFVRUJoTUNWVk14R1RBWEJnTlZCQU1NRUhKdmIzUmpZUzV3YVhwNllTNWpiMjB3SGhjTgpNakl3TnpJME1UY3lOVE15V2hjTk1qUXhNREkyTVRjeU5UTXlXakFqTVFzd0NRWURWUVFHRXdKVlV6RVVNQklHCkExVUVBd3dMS2k1d2FYcDZZUzVqYjIwd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUIKQVFEWXcwU1BkNHpObkJ4eXlVeDdCRUpEbWJ0UnNuMjNTUTlocXR4NmdGLzBpczUxM0JxNkF5OHY0YXZKbmJzdgp4cnVoc0xWZ2JKVEpMekZva0JzdEdOeHhNSnJhUlp4VFVHN3EyUXVTdFdHS3hVWXh3azZvRE14NFNDU3pnOHpuCm9YQXkxQmtnc21kQUxpREd5YVRhNDgwdkxNdncvM1VCanVTbVA0cUlTdE1DNno4NXpvc1NoV3FlSVVoamZxV3IKMUdzWUw5SGZ4eU5SMDhXOXhMRVVWL1I2Y2RHWnNKM0JITjk4OXptRTUvUTlpK242ZjdrOWVEWnZwd1ZDaFlCawpEcjhIeElxdjkrVkExb1BERFNocnRlMi8xTjc3N3ZybyttMjMzUkpGUWkyYVNvVG9WdUtDTjVoOWdRTmhNNFNYClRJNEtqY05GVk9wbWJyV1VjK0ZMbnhPQkFnTUJBQUdqZ2FVd2dhSXdDUVlEVlIwVEJBSXdBREJWQmdOVkhSRUUKVGpCTWdnc3FMbkJwZW5waExtTnZiWUlQS2k1dWJYTXVjR2w2ZW1FdVkyOXRnaE1xTG5OMFlXZHBibWN1Y0dsNgplbUV1WTI5dGdoY3FMbTV0Y3k1emRHRm5hVzVuTG5CcGVucGhMbU52YlRBZEJnTlZIUTRFRmdRVThWbDBWWFZJCmJiN1lrTm1UTXVVNldlTjVQVDh3SHdZRFZSMGpCQmd3Rm9BVW53RXkzVVp4UDl4TDBCSVJNZithYUliZHIxc3cKRFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUFOc1hBRWZlS3VkSjNpQkhpVHJEZDRoV055cCtvTEVzcEVlQ01pawpQTmdZaGROMGE5bDdRcVU2TVFtWGtXTy9hYzJPN0NrTklmU0UyNHkvOTZ2dXQyRXhLelM3UzR3LzZsempMaFNqCkV3ZUVJQjhvYTZPWVIycmlaakxMV2k4REdrZkw5cFdDcEorU2lzRkpuL1JCa2JvT0VmMDV5U1Y2aCtXNVdrRS8KOUxCU2NxZUJWUDRLelRiQ200S1dmNkc1RjhsQzBGMEZYNGtBY1RtSDhnalRoSzhqYTFNOGIxS1lXTnZzSW43dgo3dG9nNHIzVTk5eGZxRHhLdUxLRFFDclU5Wk9pc1hkVTRFbmwyUzFWaUI2Yld6RW9VekZxVHJBNmpPMUpNdTI3CkhiS3I1Mm5laWp1QndsWTY4VlZDMUpHRU9yQmtDdmxGaFNuS0hET1daOUhpbXVnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
  }
]
```

And `request_errors` is a stringified `json` array of objects like this:

```
[
  {
    "certificate_signing_request": "-----BEGIN CERTIFICATE REQUEST-----...-----END CERTIFICATE REQUEST-----",
    "error": {
      "code": 101,
      "name": "ip_not_allowed",
      "message": "IP identifiers are not allowed by this CA",
      "reason": "ip in san",
      "provider": "letsencrypt",
      "endpoint": "https://acme-staging-v02.api.letsencrypt.org/directory"
    }
  }
]
```

#### Error Codes

Errors contain both a numeric `code` (integer) and a machine-readable `name` (string).

Standard error codes:

| Code | Name | Description |
| ------- | ---------------------- | -------------------------------------------------------------- |
| **1XX** | **csr\_error** | **Errors related to the certificate request itself** |
| 101 | `ip_not_allowed` | IP addresses are not allowed in the CSR by the provider |
| 102 | `domain_not_allowed` | The domain requested by the CSR is not allowed by the provider |
| 103 | `wildcard_not_allowed` | Wildcard certificates are not allowed by the provider |
| **2XX** | **server\_error** | **Server-related errors** |
| 201 | `server_not_available` | The provider backend is not reachable (e.g., Vault is sealed) |
| **9XX** | **other** | **Other errors not covered by the above categories** |

#### Capabilities

A provider **may** optionally advertise a best-effort description of what its backing
certificate issuing capabilities via the `capabilities` field in its application data. This
field is additive and optional.

Every attribute is independently optional. An omitted attribute means "unspecified /
unknown" and **must not** be treated as an assumed default by the requirer. The `capabilities` should not be assumed by requirers and can be fully absent.

```
{
  "supports_ip_sans": false,
  "supports_wildcard_dns": true,
  "supports_subdomain": false,
  "supports_ca_certificates": false,
  "allowed_domains": ["mydomain.com"],
  "provider_type": "acme"
}
```

**Backward Compatibility**:
The `capabilities` field is optional and additive. Capability-aware requirers interoperate
with legacy providers (no `capabilities` advertised), and legacy requirers interoperate
with capability-advertising providers, with no behavioral change to existing flows.

## Charms implementing this interface

### Providers

### Requirers

## Other charms using this interface

### Providers

* [vault-k8s](https://charmhub.io/vault-k8s)
* [easyrsa](https://charmhub.io/easyrsa)
* [vault](https://charmhub.io/vault)
* [lego](https://charmhub.io/lego)
* [self-signed-certificates](https://charmhub.io/self-signed-certificates)
* [manual-tls-certificates](https://charmhub.io/manual-tls-certificates)

### Requirers

* [kafka](https://charmhub.io/kafka)
* [kafka-k8s](https://charmhub.io/kafka-k8s)
* [mongodb](https://charmhub.io/mongodb)
* [mongodb-k8s](https://charmhub.io/mongodb-k8s)
* [mysql](https://charmhub.io/mysql)
* [traefik-k8s](https://charmhub.io/traefik-k8s)
* [mysql-k8s](https://charmhub.io/mysql-k8s)
* [mysql-router](https://charmhub.io/mysql-router)
* [vault-k8s](https://charmhub.io/vault-k8s)
* [parca-k8s](https://charmhub.io/parca-k8s)
* [mysql-router-k8s](https://charmhub.io/mysql-router-k8s)
* [postgresql](https://charmhub.io/postgresql)
* [opensearch](https://charmhub.io/opensearch)
* [pgbouncer](https://charmhub.io/pgbouncer)
* [prometheus-k8s](https://charmhub.io/prometheus-k8s)
* [pgbouncer-k8s](https://charmhub.io/pgbouncer-k8s)
* [grafana-k8s](https://charmhub.io/grafana-k8s)
* [lxd](https://charmhub.io/lxd)
* [postgresql-k8s](https://charmhub.io/postgresql-k8s)
* [zookeeper](https://charmhub.io/zookeeper)
* [loki-k8s](https://charmhub.io/loki-k8s)
* [zookeeper-k8s](https://charmhub.io/zookeeper-k8s)
* [alertmanager-k8s](https://charmhub.io/alertmanager-k8s)
* [openfga-k8s](https://charmhub.io/openfga-k8s)
* [ovn-chassis](https://charmhub.io/ovn-chassis)
* [keystone-kerberos](https://charmhub.io/keystone-kerberos)
* [ovn-dedicated-chassis](https://charmhub.io/ovn-dedicated-chassis)
* [octavia](https://charmhub.io/octavia)
* [neutron-api-plugin-ovn](https://charmhub.io/neutron-api-plugin-ovn)
* [anbox-cloud-dashboard](https://charmhub.io/anbox-cloud-dashboard)
* [cinder](https://charmhub.io/cinder)
* [etcd](https://charmhub.io/etcd)
* [ceph-fs](https://charmhub.io/ceph-fs)
* [istio-pilot](https://charmhub.io/istio-pilot)
* [keystone-saml-mellon](https://charmhub.io/keystone-saml-mellon)
* [masakari](https://charmhub.io/masakari)
* [swift-proxy](https://charmhub.io/swift-proxy)
* [anbox-stream-gateway](https://charmhub.io/anbox-stream-gateway)
* [aodh](https://charmhub.io/aodh)
* [designate-bind](https://charmhub.io/designate-bind)
* [nova-cell-controller](https://charmhub.io/nova-cell-controller)
* [ceph-radosgw](https://charmhub.io/ceph-radosgw)
* [ovn-central](https://charmhub.io/ovn-central)
* [ams](https://charmhub.io/ams)
* [keystone](https://charmhub.io/keystone)
* [temporal-k8s](https://charmhub.io/temporal-k8s)
* [ceilometer](https://charmhub.io/ceilometer)
* [kubernetes-e2e](https://charmhub.io/kubernetes-e2e)
* [kubernetes-dashboard](https://charmhub.io/kubernetes-dashboard)
* [kubeapi-load-balancer](https://charmhub.io/kubeapi-load-balancer)
* [octavia-diskimage-retrofit](https://charmhub.io/octavia-diskimage-retrofit)
* [designate](https://charmhub.io/designate)
* [glance](https://charmhub.io/glance)
* [keystone-ldap](https://charmhub.io/keystone-ldap)
* [manila-ganesha](https://charmhub.io/manila-ganesha)
* [heat](https://charmhub.io/heat)
* [ironic-conductor](https://charmhub.io/ironic-conductor)
* [istio-ingress-k8s](https://charmhub.io/istio-ingress-k8s)
* [ceph-rbd-mirror](https://charmhub.io/ceph-rbd-mirror)
* [kubernetes-worker](https://charmhub.io/kubernetes-worker)
* [nginx-ingress-integrator](https://charmhub.io/nginx-ingress-integrator)
* [docker-registry](https://charmhub.io/docker-registry)
* [cinder-netapp](https://charmhub.io/cinder-netapp)
* [magnum](https://charmhub.io/magnum)
* [neutron-api](https://charmhub.io/neutron-api)
* [grafana-agent-k8s](https://charmhub.io/grafana-agent-k8s)
* [barbican-vault](https://charmhub.io/barbican-vault)
* [anbox-stream-agent](https://charmhub.io/anbox-stream-agent)
* [rabbitmq-server](https://charmhub.io/rabbitmq-server)
* [mysql-innodb-cluster](https://charmhub.io/mysql-innodb-cluster)
* [superset-k8s](https://charmhub.io/superset-k8s)
* [juju-jimm-k8s](https://charmhub.io/juju-jimm-k8s)
* [mimir-coordinator-k8s](https://charmhub.io/mimir-coordinator-k8s)
* [placement](https://charmhub.io/placement)
* [openstack-dashboard](https://charmhub.io/openstack-dashboard)
* [nats](https://charmhub.io/nats)
* [tempo-coordinator-k8s](https://charmhub.io/tempo-coordinator-k8s)
* [kubernetes-control-plane](https://charmhub.io/kubernetes-control-plane)
* [ironic-api](https://charmhub.io/ironic-api)
* [netbox-k8s](https://charmhub.io/netbox-k8s)
* [vault](https://charmhub.io/vault)
* [nova-cloud-controller](https://charmhub.io/nova-cloud-controller)
* [gnocchi](https://charmhub.io/gnocchi)
* [loki-coordinator-k8s](https://charmhub.io/loki-coordinator-k8s)
* [octavia-dashboard](https://charmhub.io/octavia-dashboard)
* [charmed-etcd](https://charmhub.io/charmed-etcd)
* [neutron-dynamic-routing](https://charmhub.io/neutron-dynamic-routing)
* [glance-simplestreams-sync](https://charmhub.io/glance-simplestreams-sync)
* [kyuubi-k8s](https://charmhub.io/kyuubi-k8s)
* [barbican](https://charmhub.io/barbican)
* [cinder-purestorage](https://charmhub.io/cinder-purestorage)
* [manila-generic](https://charmhub.io/manila-generic)
* [cinder-backup-swift-proxy](https://charmhub.io/cinder-backup-swift-proxy)
* [ceph-dashboard](https://charmhub.io/ceph-dashboard)
* [manila](https://charmhub.io/manila)
* [glauth-k8s](https://charmhub.io/glauth-k8s)
* [neutron-api-plugin-ironic](https://charmhub.io/neutron-api-plugin-ironic)
* [cinder-lvm](https://charmhub.io/cinder-lvm)
* [catalogue-k8s](https://charmhub.io/catalogue-k8s)
* [magnum-dashboard](https://charmhub.io/magnum-dashboard)
* [aws-iam](https://charmhub.io/aws-iam)
* [manila-dashboard](https://charmhub.io/manila-dashboard)
* [opentelemetry-collector-k8s](https://charmhub.io/opentelemetry-collector-k8s)
* [masakari-monitors](https://charmhub.io/masakari-monitors)
* [chrony](https://charmhub.io/chrony)
* [opentelemetry-collector](https://charmhub.io/opentelemetry-collector)
* [ceph-iscsi](https://charmhub.io/ceph-iscsi)
* [neutron-api-plugin-arista](https://charmhub.io/neutron-api-plugin-arista)
