# Configuration Redeployment



<Callout type="warn">
  This topic describes upcoming functionality that is not yet supported.
</Callout>

Overview [#overview]

The first configuration for a tenant is deployed when the tenant is created. Any subsequent deployment is called a *redeployment*. The structure of a redeployed configuration is the same as for the first deployment, but there are rules about the changes to the configuration package that must be followed to ensure compatibility with existing data in the tenant.

<span id="redeployment_safety" />

The differences between a redeployed configuration and the existing active configuration fall into one of these categories:

* **Safe** changes are allowed without restriction.
* **Migratable** changes are allowed, but will put the tenant in a special state until affected tenant data is updated to conform with the new configuration.
* **Disallowed** changes will always cause re-deployment to fail.

If all changes between the new configuration and the active configuration are *Safe*, then the redeployment will overwrite the existing active configuration.

If any of the changes in the new configuration are `Migratable` and there are no `Disallowed` changes, the system will deploy the new configuration but leave the existing configuration intact for existing Quotes, Policies, and other data. At this point there will be two configurations in the tenant. The Configuration Migration Plugin must be used to update data to conform with the new configuration, and once all data is migrated, the older configuration will be retired. Until then, only `Safe` re-deployments are allowed, using the most recent deployment as the basis for comparison.

<Callout type="warn">
  Clients can force the redeployment of unsafe changes for test tenants in non-production environments by setting the `overwrite` flag to `true`. This will cause the latest configuration to be overwritten with the configuration in the payload. This could cause system instability and data incompatibility, so should only be done with thorough testing on a test tenant. After the migration features described in this topic are delivered, it will be discouraged to bypass redeployment safety checks.
</Callout>

Safe Changes [#safe-changes]

<Callout type="warn">
  The evaluation of a configuration change as `Safe` is based on the *system's* ability to anticipate and handle certain changes. Some changes may be defined as `Safe` but cause errors or exceptions in client-created plugin code or template definitions. You should always test prospective configuration changes in a test tenant before deploying them to production.
</Callout>

The following changes are defined as `Safe` and can be deployed without restriction:

* Adding new definitions for:
  * Accounts
  * Products
  * Elements (of any category)
  * Charges
  * Custom Data Types
  * Coverage Terms
  * Documents
  * Tables
  * Installment Plans
  * Regions
  * Jurisdictions

* Changing any of these properties, either globally or for a specific product:
  * `defaultDurationBasis`
  * `defaultTermLength`
  * `defaultTimeZone`
  * `defaultCurrency`
  * `defaultTimeZone`
  * `defaultInstallmentPlan`

* Omitting any top-level property (this will be interpreted as leaving that item or class of item unchanged.)

* Adding to a product's `eligibleAccountTypes` if the list is not empty (in other words, if the restrictions are being made more liberal.)

* Removing or changing the `displayName` or any other UI support values for any item

* Making any of these changes for products or elements:
  * Adding subelements to the `contents` using the `?` or `*` quantifier

  * Changing the quantifier of any item in `contents`:
    * From `+` to `*`
    * From `(blank)` to `?`
    * From `!` to `(blank)`
    * From `(blank)` to `!` if all the requirements for the automatic quantifier are met for that element definition

  * Adding coverage terms with quantifier `?`

  * Changing the quantifier of any coverage term from `(blank)` to `?`

  * Changing the `abstract` property of any entity from `true` to `false`

  * Moving properties to or from a base entity, or adding, removing, or changing the `extend` property such that the derived entity is unchanged or has safe changes only -- and if the base entity is not `abstract`, it too has only safe changes. This means that it is the final structure of the item that is being evaluated, irrespective of whether it has that structure because of inheritance or explicit declarations.

* Making any of these changes for coverage terms:
  * Changing the default coverage term option (as indicated by the `*` prefix)
  * Changing the `value` or `tag` of any coverage term option

* Making any of these changes to data extension properties:
  * Removing `min` or making it a smaller (or more negative) value
  * Removing `max` or making it a larger (or less negative) value
  * Removing `minLength` or making it a smaller value
  * Removing `maxLength` or making it a larger value
  * Removing `regex`
  * Adding to the `options` list for a property that already has at least one option
  * Removing the `options` list
  * Increasing the `precision` of a numeric property
  * Adding or changing the `defaultValue`
  * Removing a required (`(blank)` or `+`) data extension, or making them optional (`?` or `*`, respectively)
  * Adding a new required data extension, or changing it from optional to required, **with** a `defaultValue` (see <ApiLink name="PropertyRef" />). The default value will be used whenever a record is changed and no other value is provided, ensuring that the system is able to validate the record against the current configuration. Historical data will not be updated otherwise.

Migratable Changes [#migratable-changes]

Some changes are defined as `Migratable`. A deployment with such changes (and no `Disallowed`) will cause the system to deploy the new configuration while leaving the existing configuration in place and leaving it associated with existing data. The system will evaluate each entity and if it conforms to the new configuration without change, automatically re-associate it with the new configuration. For those items that aren't compatible with the new configuration, the Configuration Migration Plugin must change the existing data to conform with the new configuration.

<Callout type="warn">
  **All** data must be migrated to the new configuration in order for subsequent non-safe redeployments to be allowed.
</Callout>

Migration is done by sending either the entire account or an array of affected policy terms and segments to the plugin. (It's likely that there will be different entry points for different migratable types.)

The following changes are defined as `Migratable`:

* Adding data extension properties with `(blank)` or `+` quantifiers
* Making data extensions more restrictive, such as increasing the `min` value or reducing the `maxLength` value
* Adding coverage terms to a product or element with a `(blank)` quantifier

If the result of the Configuration Migration Plugin is that new data does not result in only `Safe` changes for that data, the migration will fail. An event called `configuration.migration.failure` will be added to the event stream for that data.

APIs will be added to:

* Find all items that have failed migration
* Retrigger migration after the plugin or the configuration has been updated

<Callout>
  We *may* add a feature so that the client can force additional data to be sent to the Configuration Migration Plugin even if that data is fully compatible with the new configuration. This is being evaluated.
</Callout>

Disallowed Changes [#disallowed-changes]

Any change not specifically indicated as `Safe` or `Migratable` is `Disallowed`. This includes, but is not limited to, these changes:

* Making any of these changes to a product or element definition:
  * Changing the quantifier of any of its `contents`:
    * From `*` or `?` to any other value
    * To `!` if the requirements are not met for automatic creation of the element

  * Removing an element from a product's or element's `contents` list

  * Changing the quantifier for a coverage term from `?` to `blank`, or removing a coverage term

* Removing a coverage term option from a coverage term

Future Functionality [#future-functionality]

Locking [#locking]

A future release will include an option called *Locking* for handling migration in the Configuration Migration Plugin. Instead of modifying the data to conform with the configuration, the entity, or a term within a policy, can be *locked* and thereby deemed to be compliant with any configuration. There are some important considerations:

* Accounts may not be locked unless they have no policies or all their policies are locked

* A term can only be locked if:
  * Its `endTime` is in the past; and
  * All terms that precede the term being locked in the policy as also locked or becoming locked

* A policy can only be locked if it is expired (with its last term's `endTime` in the past) or cancelled

* No policy transaction can be effective before the last locked term's `endTime` in a policy

* UI support may not work for locked entities that don't conform to the configuration

* Locking is a one-way operation; there is no unlock functionality

An API will allow entity and term locking outside of the migration process.

<Callout>
  Locking does not enable the deployment of disallowed changes.
</Callout>

Retirement [#retirement]

A future release will support retirement of configuration definitions for accounts, products, elements, coverage terms, data extension properties, and installment plans. The definitions for these items will support a `status` property which can have one of these values:

* `active`: The item can be used as normal. This is the default status.
* `retired`: The item cannot be added to any existing data (for example, retired elements can't be added to a policy with a policy change.) Existing data of the type can continue to exist, but transactions that attempt to add new instances will fail to validate.
* `nonRenew`: A renewal must remove the item in order to validate. For installment plans, the renewal must change the selected plan. If a product has `nonRenew` status, renewal transactions will not validate.

Changing the `status` of an item is always a Safe change.

<Callout>
  There *may* be a feature to specify an `effectiveTime` for the `status` property. This would mean that the system will treat the item as `active` until the system time is on or after the `effectiveTime`. The need for such a feature is being evaluated.
</Callout>
