

Amazon Cloud Directory is no longer be open to new customers. For alternatives to Cloud Directory, explore [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) and [Amazon Neptune](https://aws.amazon.com/neptune/). If you need help choosing the right alternative for your use case, or for any other questions, contact [AWS Support](https://aws.amazon.com/support/). 

# Schemas


With Amazon Cloud Directory, schemas define what types of objects can be created within a directory (users, devices, and organizations), enforce validation of data for each object class, and handle changes to the schema over time. More specifically, a schema defines the following:
+ One or more types of facets that may be mapped to objects within a directory (such as Person, Organization\$1Person)
+ Attributes that may be mapped to objects within a directory (such as Name, Description). Attributes can be required or made optional on various types of facets, and are defined within the context of a facet. 
+ Constraints that may be enforced on object attributes (such as Required, Integer, String) 

When a schema has been applied to a directory, all data within that directory must then conform to that applied schema. In this way, the schema definition is essentially a blueprint that can be used to construct multiple directories with applied schemas. Once built, those applied schemas may vary from the original blueprint, each in different ways. 

Applied schemas can later be updated using versioning and then reapplied to all the directories that use it. For more information, see [In-Place Schema Upgrade](schemas_inplaceschemaupgrade.md).

Cloud Directory provides API operations to create, read, update, and delete schemas. This allows the contents of the schema to be easily consumed by programmatic agents. Such agents access the directory to discover the full set of facets, attributes, and constraints that apply to data within the directory. For more information about the schema APIs, see the [Amazon Cloud Directory API Reference Guide](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/welcome.html).

Cloud Directory supports uploading a compliant JSON file for schema creation. You can also create and manage schemas using the Directory Service console. For more information, see [Create an Amazon Cloud Directory](getting_started_create_directory.md).

**Topics**
+ [

# Schema Lifecycle
](schemas_lifecycle.md)
+ [

# Facets
](schemas_whatarefacets.md)
+ [

# In-Place Schema Upgrade
](schemas_inplaceschemaupgrade.md)
+ [

# Managed Schema
](schemas_managed.md)
+ [

# Sample Schemas
](schemas_sampleschemastopic.md)
+ [

# Custom Schemas
](schemas_customschematopic.md)
+ [

# Attribute References
](schemas_attributereferences.md)
+ [

# Attribute Rules
](schemas_attributerules.md)
+ [

# Format Specification
](schemas_jsonformat.md)

# Schema Lifecycle


Cloud Directory offers a schema lifecycle to help with the development of schemas. This lifecycle consists of three states: Development, Published, and Applied. These states are designed to facilitate construction and distribution of schemas. Each of these states has different features aiding this effort. 

The following diagram depicts possible transitions and verbiage. All schema transitions are copy-on-write. For example, publishing a development schema does not alter or remove the development schema. 

![\[Diagram showing schema transitions: Development to Published to Applied, with Deleted option.\]](http://docs.aws.amazon.com/clouddirectory/latest/developerguide/images/schema_lifecycle.png)


You can delete a schema when it is in either the Development or Published state. Deleting a schema cannot be undone nor can it be restored once it has been deleted.

Schemas in Development, Published and Applied states have ARNs that represent them. These ARNs are used in API operations to describe the schema that the API operates on. It is easy to discern the state of a schema by looking at a schema ARN.
+ Development: `arn:aws:clouddirectory:us-east-1:1234567890:schema/development/SchemaName`
+ Published: `arn:aws:clouddirectory:us-east-1:1234567890:schema/published/SchemaName/Version`
+ Applied: `arn:aws:clouddirectory:us-east-1:1234567890:directory/directoryid/schema/SchemaName/Version`

## Development State


Schemas are initially created in the development state. Schemas in this state are fully mutable. You can freely add or remove facets and attributes. The majority of schema design occurs in this state. Schemas in this state have a name but no version.

## Published State


The published schema state stores schemas that are ready to be applied to data directories. Schemas are published from the development state into the published state. You cannot change schemas in the published state. You can apply published schemas to any number of data directories. 

Published and applied schemas must have a version associated with them. For more information about versions, see [Schema Versioning](schemas_inplaceschemaupgrade.md#schemas_cdschemaversion).

## Applied State


A published schema can be applied to data directories. A schema that has been applied to a data directory is said to be applied. Once you apply a schema to a data directory, you can use the schema's facets when creating objects. You can apply multiple schemas to the same data directory. Only the following changes are permitted on an applied schema.
+  Add a facet to an applied schema
+  Add a non-required attribute to an applied schema

# Facets


Facets are the most basic abstraction within a schema. They represent a set of attributes that can be associated with an object in the directory and are similar in concept to LDAP object classes. Each directory object may have up to a certain number of facets associated with it. For more information, see [Amazon Cloud Directory Limits](limits.md). 

Each facet maintains its own independent set of attributes. Each facet consists of fundamental metadata, such as the facet name, version information, and behaviors. The combination of schema ARNs, facets, and attributes define uniqueness on the object. 

The set of object facets, their constraints, and the relationships between them constitute an abstract schema definition. Schema facets are used to define constraints over the following things: 

1. Attributes allowed in an object

1. Policy types allowed to apply to an object 

Once you have added the necessary facets to your schema, you can apply the schema to your directory and create the applicable objects. For example, you can define a device schema by adding facets such as computers, phones, and tablets. You can then use these facets to create computer objects, phone objects, and tablet objects in the directory to which the schema applies.

Cloud Directory’s schema support makes it easy to add or modify facets and attributes without worrying about breaking applications. For more information, see [In-Place Schema Upgrade](schemas_inplaceschemaupgrade.md).

# In-Place Schema Upgrade


Cloud Directory offers the updating of existing schema attributes and facets to help integrate your applications with AWS provided services. Schemas that are in either the published or applied states have versions and cannot be changed. For more information, see [Schema Lifecycle](schemas_lifecycle.md). 

## Schema Versioning


A schema version indicates a unique identifier for a schema that developers can specify when programming their applications to conform to certain rules and formatting of data. Two key differentiators in the way versioning works with Cloud Directory are important for developers to understand. These differentiators—major version and minor version—can determine how future schema upgrades impact your application.

### Major Version


*Major version* is the version identifier used for tracking major version changes for a schema. It can be up to 10 characters in length. Different versions of the same schema are completely independent. For example, two schemas with the same name and different versions are treated as completely different schemas, which have their own namespaces. 

**Backward incompatible changes**

We recommend making changes to the major version only when schemas are incompatible. For example, when changing the data type of an existing attribute (such as changing from `string` to `integer`) or dropping a mandatory attribute from your schema. Backward-incompatible changes require directory data migration from a previous schema version to the new schema version.

### Minor Version


*Minor version* is the version identifier used for in-place upgrading of schemas or when you want to make backward-compatible upgrades such as adding additional attributes or adding facets. An upgraded schema using a minor version can be applied in place across all directories that use it without breaking any running applications. This includes directories that are used in production environments. For an example use case, see [“How to Easily Apply Amazon Cloud Directory Schema Changes with In-Place Schema Upgrades”](https://aws.amazon.com/blogs/security/how-to-easily-apply-amazon-cloud-directory-schema-changes-with-in-place-schema-upgrades/) in the Cloud Directory Blog.

The minor version information and history is saved along with the other schema information in the schema metadata repository. No minor version information is retained in the objects. The advantage of introducing minor version is that client code works seamlessly as long as the major version is not changed.

**Minor Version Limits**

Cloud Directory retains and therefore limits up to five minor versions. However, minor version limits are enforced differently for published and applied schemas in the following ways:
+ **Applied schemas:** Once the minor version limit has been exceeded, Cloud Directory deletes the oldest minor version automatically.
+ **Published schemas:** Once the minor version limit has been exceeded, Cloud Directory does not delete any of the minor versions but it does inform the user via a `LimitExceededException` that the limit has been exceeded. Once you exceed the minor version limits, you can either delete the schema by using the [DeleteSchema](https://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_DeleteSchema.html) API or request a limit raise.

## Using the Schema Upgrade API Operations


You can use the [http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_UpgradePublishedSchema.html](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_UpgradePublishedSchema.html) API call to upgrade published schemas. Schema upgrades are applied in place to the directories that rely on it using the [http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_UpgradeAppliedSchema.html](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_UpgradeAppliedSchema.html) API call. You can also fetch the major and minor version of an applied schema by calling [http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_GetAppliedSchemaVersion.html](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_GetAppliedSchemaVersion.html)s. Or view the associated schema ARNs and schema revision history for a directory by calling [http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_ListAppliedSchemaArns.html](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_ListAppliedSchemaArns.html). Cloud Directory maintains the five most recent versions of applied schema changes. 

For an illustrative example, see [“How to Easily Apply Amazon Cloud Directory Schema Changes with In-Place Schema Upgrades”](https://aws.amazon.com/blogs/security/how-to-easily-apply-amazon-cloud-directory-schema-changes-with-in-place-schema-upgrades/) in the Cloud Directory Blog. The blog post will demonstrate how you perform an in-place schema upgrade and use schema versions in Cloud Directory. It covers how to add additional attributes to an existing facet, add a new facet to a schema, publish the new schema, and apply it to running directories to complete the upgrading of a schema in-place. It also shows how to view the version history of a directory schema, which helps to ensure the directory fleet is running the same version of the schema and has the correct history of schema changes applied to it.

# Managed Schema


Cloud Directory makes it easy for you to rapidly develop applications by using a managed schema. With a managed schema, you can create a directory and start creating and retrieving objects from it at a faster pace. For more information, see [Create Your Directory](how_to_manage_directory_create.md).

Currently, there is one managed schema, called the `QuickStartSchema`. You can build a rich hierarchical data model and establish relationships across objects by using constructs such as [Typed Links](directory_objects_links.md#directory_objects_links_typedlink). You can then query for any information in your data by traversing the hierarchy. 

The `QuickStartSchema` managed schema is represented by the following JSON: 

```
QuickStartSchema: {
    "facets": {
        "DynamicObjectFacet": {
            "facetStyle": "DYNAMIC"
        },
        "DynamicTypedLinkFacet": {
            "facetAttributes": {
                "DynamicTypedLinkAttribute": {
                    "attributeDefinition": {
                        "attributeRules": {},
                        "attributeType": "VARIANT",
                        "isImmutable": false
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "identityAttributeOrder": [
                "DynamicAttribute"
            ]
        }
    }
}
```

**QuickStartSchema ARN**

The `QuickStartSchema` managed schema uses the following ARN:

```
String QUICK_START_SCHEMA_ARN = "arn:aws:clouddirectory:::schema/managed/quick_start/1.0/001" ;
```

For example, you could use this ARN to create a directory called `ExampleDirectory` as shown below:

```
CreateDirectoryRequest createDirectoryRequest = new CreateDirectoryRequest()
    .withName("ExampleDirectory") // Directory name
    .withSchemaArn(QUICK_START_SCHEMA_ARN);
```

## Facet Styles


There are two different styles that you can define on any given facet, `Static` and `Dynamic`.

### Static Facets


Static facets are the best choice when you have all the details of your data model for your directory, such as a list of attributes with their data types, and you also want to define constraints for your attributes such as mandatory or unique fields. Cloud Directory will enforce the data constraints and rule checking during your object creation or change.

### Dynamic Facets


You can use a dynamic facet when you need flexibility to change the number of attributes or change the data values being stored within your attributes. Cloud Directory does not enforce any data constraints and rule checking during your object creation or change.

After creating a schema with dynamic facets, you can define any attributes that you need while creating objects. Cloud Directory will accept the attributes as key-value pairs and store them on their provided objects.

You can add a dynamic facet to a new or existing schema. You can also combine the static and dynamic facets within a single schema to get benefits for each style of facet within your directory.

When you create any attribute using Dynamic facet, they are created as `Variant` data type. To store values for the attribute defined as a `Variant` data type, you can use values of any of the primitive data types supported in Cloud Directory, such as `String` or `Binary`. Over time, you can also change the value of the attribute to another datatype. There is no enforcement of data validation.

You can use dynamic facets to define objects of the following type:
+ `NODE`
+ `LEAF_NODE`
+ `POLICY`

For additional details about managed schemas, dynamic facets or variant data types and to see example use cases, see [How to rapidly develop applications on Amazon Cloud Directory using AWS Managed Schema](https://aws.amazon.com/blogs/database/rapidly-develop-applications-on-amazon-cloud-directory-with-managed-schema/) in the Amazon Cloud Directory blog.

# Sample Schemas


Cloud Directory comes ready with sample schemas for Organizations, Persons, and Devices. The following section lists the various sample schemas and lists the differences for each.

## Organizations


The following tables list the facets that are included in the *Organizations* sample schema.

 


****  

| **"Organization" Facet ** | **Data Type ** | **Length ** | **Required Behavior? ** | **Description ** | 
| --- | --- | --- | --- | --- | 
| account\$1id  | String  | 1024  | N  | Unique id for Organization  | 
| account\$1name  | String  | 1024  | N  | Name of Organization  | 
| organization\$1status  | String  | 1024  | N  | Status such as 'active', 'suspended', 'inactive', 'closed'  | 
| mailing\$1address (street1)  | String  | 1024  | N  | A physical mailing address for this company/entity  | 
| mailing\$1address (street2)  | String  | 1024  | N  | A physical mailing address for this company/entity  | 
| mailing\$1address (city)  | String  | 1024  | N  | A physical mailing address for this company/entity  | 
| mailing\$1address (state)  | String  | 1024  | N  | A physical mailing address for this company/entity  | 
| mailing\$1address (country)  | String  | 1024  | N  | A physical mailing address for this company/entity  | 
| mailing\$1address (postal\$1code)  | String  | 1024 | N  | A physical mailing address for this company/entity  | 
| email  | String  | 1024  | N  | Email id for Organization  | 
| web\$1site  | String  | 1024  | N  | Website URL  | 
| telephone\$1number  | String  | 1024  | N  | Telephone number for Organization  | 
| description  | String  | 1024  | N  | Description for Organization  | 

 


****  

| **"Legal\$1Entity" Facet ** | **Data Type** | **Length**  | **Required Behavior?**  | **Description** | 
| --- | --- | --- | --- | --- | 
| registered\$1company\$1name  | String  | 1024  | N  | Legal entity name  | 
| mailing\$1address (street1)  | String  | 1024  | N  | A physical registered address for this company/entity  | 
| mailing\$1address (street2)  | String  | 1024  | N  | A physical registered address for this company/entity  | 
| mailing\$1address (city)  | String  | 1024  | N  | A physical registered address for this company/entity  | 
| mailing\$1address (state)  | String  | 1024  | N  | A physical registered address for this company/entity  | 
| mailing\$1address (country)  | String  | 1024  | N  | A physical registered address for this company/entity  | 
| mailing\$1address (postal\$1code)  | String  | 1024  | N  | A physical registered address for this company/entity  | 
| industry\$1vertical  | String  | 1024  | N  | Industry Segment  | 
| billing\$1currency  | String  | 1024  | N  | Billing currency  | 
| tax\$1id  | String  | 1024  | N  | Tax identification number  | 

## Person


The following tables list the facets that are included in the *Person* sample schema.

 


****  

| **"Person" Facet** | **Data Type** | **Length** | **Required Behavior?** | **Description** | 
| --- | --- | --- | --- | --- | 
| display\$1name | String | 1024 | N | The name of the user, suitable for display to end-users. | 
| first\$1name | String | 1024 | N | The given name of the User, or first name in most western languages | 
| last\$1name | String | 1024 | N | The family name of the User, or last name in most western languages | 
| middle\$1name | String | 1024 | N | The middle name(s) of the User | 
| nickname | String | 1024 | N | The casual way to address the user in real life, such as, "Bob" or "Bobby" instead of "Robert" | 
| email | String | 1024 | N | Email address for the user | 
| mobile\$1phone\$1number | String | 1024 | N | Phone number for the user | 
| home\$1phone\$1number | String | 1024 | N | Phone number for the user | 
| username | String | 1024 | Y | unique identifier for the user | 
| profile | String | 1024 | N | A URI that is a uniform resource locator and that points to a location representing the user's online profile (such as a webpage) | 
| picture | String | 1024 | N | A URI that is a uniform resource locator that points to a resource location representing the user's image. | 
| website | String | 1024 | N | URL | 
| timezone | String | 1024 | N | The User's time zone | 
| locale | String | 1024 | N | Used to indicate the User's default location for purposes of localizing such items as currency, date time format, or numerical representations. | 
| address (street1) | String | 1024 | N | A physical mailing address for this user. | 
| address (street2) | String | 1024 | N | A physical mailing address for this user. | 
| address (city) | String | 1024 | N | A physical mailing address for this user. | 
| address (state) | String | 1024 | N | A physical mailing address for this user. | 
| address (country) | String | 1024 | N | A physical mailing address for this user. | 
| address (postal\$1code) | String | 1024 | N | A physical mailing address for this user. | 
| user\$1status | String | 1024 | N | Value indicating the user's administrative status | 

 


****  

| **"Organization\$1Person" Facet** | **Data Type** | **Length** | **Required Behavior?** | **Description** | 
| --- | --- | --- | --- | --- | 
| title | String | 1024 | N | Title in organization | 
| preferred\$1language | String | 1024 | N | Indicates the user's preferred written or spoken languages and is generally used for selecting a localized user interface. | 
| employee\$1id | String | 1024 | N | A string identifier, typically numeric or alphanumeric, assigned to a person | 
| cost\$1center | Integer | 1024 | N | Identifies the cost center | 
| department | String | 1024 | N | Identifies the name of a department | 
| manager  | String | 1024 | N | The user's manager | 
| company\$1name | String | 1024 | N | Identifies the name of an organization | 
| company\$1address (street1) | String | 1024 | N | A physical mailing address for the organization | 
| company\$1address (street2) | String | 1024 | N | A physical mailing address for the organization | 
| company\$1address (city) | String | 1024 | N | A physical mailing address for the organization | 
| company\$1address (state) | String | 1024 | N | A physical mailing address for the organization | 
| company\$1address (country) | String | 1024 | N | A physical mailing address for the organization | 
| company\$1address (postalCode) | String | 1024 | N | A physical mailing address for the organization | 

## Device


The following table lists the facet that is included in the *Device* sample schema.

 


****  

| **"Device" Facet** | **Data Type** | **Length** | **Required Behavior?** | **Description** | 
| --- | --- | --- | --- | --- | 
| device\$1id | String | 1024 | N | Alpha-numeric unique device id | 
| name | String | 1024 | N | Friendly name for device | 
| description  | String | 1024 | N | Description for device  | 
| X.509\$1certificates | String | 1024 | N | X.509 Certificate | 
| device\$1version | String | 1024 | N | Device version  | 
| device\$1os\$1type | String | 1024 | N | Operating System on device | 
| device\$1os\$1version | String | 1024 | N | Operating System version number on device | 
| serial\$1number | String | 1024 | N | Serial number of device | 
| device\$1status | String | 1024 | N | Status for device (such as active, not\$1active, suspended, shutdown, off) | 

# Custom Schemas


The first step in creating a custom schema is to define exactly what fields you must index. These required fields form your schema's skeleton elements, to which you add your own fields. Map the name and type of each field (such as string, integer, Boolean) to your object's structure. You can define a schema with types and constraints and then apply them to a directory. Once defined, Cloud Directory performs validation for attributes.

For more information, see [Create a Schema](getting_started_create_schema.md).

# Attribute References


Amazon Cloud Directory facets contain attributes. Attributes can be either an attribute definition or an attribute reference. Attribute definitions are attributes that declare their name and primitive type (string, binary, Boolean, DateTime, or number). They can also optionally declare their required behavior, default value, immutable flag, and attribute rules (such as min/max length).

Attribute references are attributes that derive their primitive type, default value, immutable flag and attribute rules from another preexisting attribute definition. Attribute references do not have their own primitive type, default values, immutable flag or rules, since those properties come from the target attribute definition.

Attribute references may override the required behavior of a target definition (more details about this below).

When you create an attribute reference, you provide only an attribute name and the target attribute definition (which includes the facet name and attribute name of the target attribute definition). Attribute references may not refer to other attribute references. Also, at this time, attribute references may not target attribute definitions from a different schema.

You can use an attribute reference when you want two or more attributes on an object to refer to the same storage location. For example, imagine an object that has a User facet and an EnterpriseUser facet applied. The User facet has a FirstName attribute definition, while the EnterpriseUser facet has an attribute reference pointing at User.FirstName. Since both FirstName attributes refer to the same storage location on the object, any change to either the User.FirstName or the EnterpriseUser.FirstName has the same effect. 

## API Example


The following example demonstrates the use of attribute references using the Cloud Directory API. In this example, a base facet contains an attribute definition, and another facet contains an attribute referring to an attribute in the base facet. Note that the reference attribute can be marked Required while the base facet is Not Required. 

```
    // create base facet
    CreateFacetRequest req1 = new CreateFacetRequest()
      .withSchemaArn(devSchemaArn)
      .withName("baseFacet")
      .withAttributes(List(
        new FacetAttribute()
          .withName("baseAttr")
          .withRequiredBehavior(RequiredAttributeBehavior.NOT_REQUIRED)
          .withAttributeDefinition(new FacetAttributeDefinition().withType(FacetAttributeType.STRING))))
      .withObjectType(ObjectType.DIRECTORY)
    cloudDirectoryClient.createFacet(req1)

    // create another facet that refers to the base facet
    CreateFacetRequest req2 = new CreateFacetRequest()
      .withSchemaArn(devSchemaArn)
      .withName("facetA")
      .withAttributes(List(
        new FacetAttribute()
          .withName("ref")
          .withRequiredBehavior(RequiredAttributeBehavior.REQUIRED_ALWAYS)
          .withAttributeReference(new FacetAttributeReference()
            .withTargetFacetName("baseFacet")
            .withTargetAttributeName("baseAttr"))))
      .withObjectType(ObjectType.DIRECTORY)
    cloudDirectoryClient.createFacet(req2)
```

## JSON Example:


The following example demonstrates the use of attribute references in a JSON model. The schema represented by this model is identical to the model above. 

```
 {
  "facets" : {
    "baseFacet" : {
      "facetAttributes" : {
        "baseAttr" : {
          "attributeDefinition" : {
            "attributeType" : "STRING"
          },
          "requiredBehavior" : "NOT_REQUIRED"
        }
      },
      "objectType" : "DIRECTORY"
    },
    "facetA" : {
      "facetAttributes" : {
        "ref" : {
          "attributeReference" : {
            "targetFacetName" : "baseFacet",
            "targetAttributeName" : "baseAttr"
          },
          "requiredBehavior" : "REQUIRED_ALWAYS"
        }
      },
      " objectType" : "DIRECTORY"
    }
}
```

### Attribute reference considerations


Attribute references must target a preexisting attribute definition in the same schema.
+ Attribute references may target a preexisting attribute definition in the same facet or a different facet.
+ Attribute references may not target other attribute references.
+ Facets containing attribute definitions that are the target of another facet's attribute reference cannot be deleted until all references have been deleted.

You can use attribute references the same way that you use traditional attribute definitions, by creating objects or applying facets to existing objects.

**Note**  
You can apply facets with references to other facets but are not required to apply the target facets directly. When the target facet is not applied, there is no change to the behavior of the attribute reference. (You need to apply target facets only when you want the other attributes on that facet to exist on the object.)

### Setting Attribute Reference Values


You can call the [UpdateObjectAttributes](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_UpdateObjectAttributes.html) API action when you want to change the value of an attribute. Updating (or deleting) either the definition or any other reference to that same definition on that object has the same effect. 

### Getting Attribute Reference Values


You can call the [ListObjectAttributes](http://docs.aws.amazon.com/clouddirectory/latest/APIReference/API_ListObjectAttributes.html) API action to retrieve storage aliases. This call returns a list of tuples, each of which contains an attribute key and its associated value. The attribute keys correspond to the list of storage aliases present on that object.

**Note**  
It is possible for an attribute key to be returned for a facet that was not explicitly applied to an object. This can happen when attribute references target facets that are not applied to the object.

For example, imagine that you have a User facet and an EnterpriseUser facet. The EnterpriseUser.FirstName attribute refers to User.FirstName. You then apply both the User and EnterpriseUser facets to an object, set User.FirstName to Robert, and later set EnterpriseUser.FirstName to Bob. When you call ListObjectAttributes you see only "User.FirstName = Bob" since there is only one storage alias for both FirstName attributes.

### Using Indexes with Attribute References


You can can create indexes with an attribute definition only, not a reference. Listing an index does not return attribute keys for attribute references. But it does return attribute keys for any attribute definitions that are targeted by references existing on the indexed object. In other words, at the index layer, attribute references are treated merely as an alternative identifier for an attribute, which gets resolved to the correct attribute definition identifier at runtime.

For example, imagine you have an Index for facet User attribute FirstName. You attach an object with only the EnterpriseUser facet applied. You then set the value for that object's EnterpriseUser.FirstName attribute to Bob. Finally, you call ListIndex action. The results contain only "User.FirstName = Bob".

### Required Behavior for Attribute References


An attribute references can have a required behavior that is different from its target attribute definition. This allows a base definition to be optional, while a reference to that same definition can be required. When an object has a base definition and one or more references to the same base definition, the base definition and all references must adhere to the strongest required behavior present across all related attributes.
+ As with attribute definitions, you must provide values for any required attribute definitions when you create the object or when you add a facet to an existing object.
+ As a convenience, when more than one attribute on an object refers to the same storage location, you only need to provide a value for one of the attributes for that storage location.
+ Similarly, if you do provide multiple values for the same storage location, the values must be equal.

# Attribute Rules


Rules describe permissible values of an attribute type and constrain the values that are allowed for any particular attribute. You must specify rules as part of an attribute definition when you create a facet. Cloud Directory supports the following rule types:
+  String length
+  Binary length
+  String from set
+  Number comparison

**String length **

Constrains the length of a string attribute value.

Allowed rule parameter keys: min, max

Allowed rule parameter values: number

**Binary length**

Constrains the byte array length of a binary attribute value.

Allowed rule parameter keys: min, max

Allowed rule parameter values: number

**String from set**

Constrains the value of a string attribute to the allowed set of specified strings. 

Allowed rule parameter keys: allowedValues

Allowed rule parameter values: Set of strings with each string to be UTF-8 encoded

Allowed values are comma delimited and can be wrapped in quotes. This is useful when allowed values include comma’s. For example:
+ One,two,three = matches One two or three
+ “with,comma”,”withoutcomma” = matches “with,comma” or “withoutcomma”
+ with”quote,withoutquote matches ‘with”quote’ or ‘withoutquote’

**Number comparison**

Constraints the numeric value allowed for a number attribute.

Allowed rule parameter keys: min, max

Allowed rule parameter values: number

# Format Specification


A Cloud Directory schema adds structure to the data in your data directories. Cloud Directory provides two mechanisms for you to define your schema. Developers can use specific API operations to construct a schema or they can upload a schema entirely using schema upload capabilities. Schema documents can be uploaded via API calls or through the console. This section describes the format to use when you upload entire schema documents.

## JSON Schema Format


A schema document is a JSON document in the following overall format. 

```
{
    "facets": {
        "facet name": {
            "facetAttributes": {
                "attribute name": Attribute JSON Subsection
            }
        }
    }
}
```

A schema document contains a map of facet names to facets. Each facet in turn contains a map containing attributes. All facet names within a schema must be unique. All attribute names within a facet must be unique.

### Attribute JSON Subsection


Facets contain attributes. Each attribute defines the type of value that can be stored on an attribute. The following JSON format describes an attribute.

```
{
    "attributeDefinition": Attribute Definition Subsection,
    "attributeReference": Attribute Reference Subsection,
    "requiredBehavior": "REQUIRED_ALWAYS" or "NOT_REQUIRED"
}
```

You must provide either an attribute definition or an attribute reference. See related subsections for more information about each. 

The required behavior field indicates whether this attribute is required or not. You must provide this field. Possible values are as follows:
+ `REQUIRED_ALWAYS`: This attribute must be provided when the object is created or a facet is added to the object. You cannot remove this attribute.
+ `NOT_REQUIRED`: This attribute may or may not be present.

### Attribute Definition Subsection


An attribute defines the type and the rules associated with an attribute value. The following JSON layout describes the format.

```
{
    "attributeType": One of "STRING", "NUMBER", "BINARY", "BOOLEAN" or "DATETIME",
    "defaultValue": Default Value Subsection,
    "isImmutable": true or false,
    "attributeRules": "Attribute Rules Subsection"
}
```

### Default Value Subsection


Specify exactly one of the following default values. Long values and Boolean values should be provided outside of quotes (as their respective Javascript types instead of strings). Binary values are provided using a URL-safe Base64 encoded string (as described in RFC 4648). Datetimes are provided in the number of milliseconds since the epoch (00:00:00 UTC on Jan 1, 1970).

```
{ 
	"stringValue": "a string value",
	"longValue": an integer value,
	"booleanValue": true or false,
	"binaryValue": a URL-safe Base64 encoded string,
	"datetimeValue": an integer value representing milliseconds since epoch
}
```

### Attribute Rules Subsection


Attributes rules define constraints on attribute values. You can define multiple rules for each attribute. Attribute rules contain a rule type and a set of parameters for the rule. You can find more details in the [Attribute Rules](schemas_attributerules.md) section. 

```
{
    "rule name": {
        "parameters": {
            "rule parameter key 1": "value",
            "rule parameter key 2": "value"
        },
        "ruleType": "rule type value"
    }
}
```

### Attribute Reference Subsection


Attribute references are an advanced feature. They allow multiple facets to share an attribute definition and stored value. See the [Attribute References](schemas_attributereferences.md) section for more information. You can define an attribute reference in JSON schema with the following template.

```
{
	"targetSchemaArn": "schema ARN"
	"targetFacetName": "facet name"
	"targetAttributeName": "attribute name"
}
```

## Schema Document Examples


The following are samples of schema documents that show valid JSON formatting.

**Note**  
All values expressed in the `allowedValues` string must be comma separated and be without spaces. For example, `"SENSITIVE,CONFIDENTIAL,PUBLIC"`.

### Basic Schema Document


```
{
    "facets": {
        "Employee": {
            "facetAttributes": {
                "Name": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": false,
                        "attributeRules": {
                            "NameLengthRule": {
                                "parameters": {
                                    "min": "3",
                                    "max": "100"
                                },
                                "ruleType": "STRING_LENGTH"
                            }
                        }
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "EmailAddress": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {
                            "EmailAddressLengthRule": {
                                "parameters": {
                                    "min": "3",
                                    "max": "100"
                                },
                                "ruleType": "STRING_LENGTH"
                            }
                        }
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "Status": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": false,
                        "attributeRules": {
                            "rule1": {
                                "parameters": {
                                    "allowedValues": "ACTIVE,INACTIVE,TERMINATED"
                                },
                                "ruleType": "STRING_FROM_SET"
                            }
                        }
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "LEAF_NODE"
        },
        "DataAccessPolicy": {
            "facetAttributes": {
                "AccessLevel": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {
                            "rule1": {
                                "parameters": {
                                    "allowedValues": "SENSITIVE,CONFIDENTIAL,PUBLIC"
                                },
                                "ruleType": "STRING_FROM_SET"
                            }
                        }
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "POLICY"
        },
        "Group": {
            "facetAttributes": {
                "Name": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "NODE"
        }
    }
}
```

### Schema Document with Typed Links


```
{
    "sourceSchemaArn": "",
    "facets": {
        "employee_facet": {
            "facetAttributes": {
                "employee_login": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "employee_id": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "employee_name": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "employee_role": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "LEAF_NODE"
        },
        "device_facet": {
            "facetAttributes": {
                "device_id": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "device_type": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "NODE"
        },
        "region_facet": {
            "facetAttributes": {},
            "objectType": "NODE"
        },
        "group_facet": {
            "facetAttributes": {
                "group_type": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "NODE"
        },
        "office_facet": {
            "facetAttributes": {
                "office_id": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "office_type": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "office_location": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": true,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "objectType": "NODE"
        }
    },
    "typedLinkFacets": {
        "device_association": {
            "facetAttributes": {
                "device_type": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": false,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                },
                "device_label": {
                    "attributeDefinition": {
                        "attributeType": "STRING",
                        "isImmutable": false,
                        "attributeRules": {}
                    },
                    "requiredBehavior": "REQUIRED_ALWAYS"
                }
            },
            "identityAttributeOrder": [
                "device_label",
                "device_type"
            ]
        }
    }
}
```