diff --git a/config/spotbugs/filter.xml b/config/spotbugs/filter.xml
index 89d72fb1a01..095a160b568 100644
--- a/config/spotbugs/filter.xml
+++ b/config/spotbugs/filter.xml
@@ -136,4 +136,10 @@
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
index 0cb9efda768..8fd75a22602 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -28,3 +28,4 @@ include ":smithy-waiters"
include ":smithy-aws-cloudformation-traits"
include ":smithy-aws-cloudformation"
include ":smithy-validation-model"
+include ":smithy-rules-engine"
diff --git a/smithy-rules-engine/build.gradle b/smithy-rules-engine/build.gradle
new file mode 100644
index 00000000000..35563660bc0
--- /dev/null
+++ b/smithy-rules-engine/build.gradle
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+description = "Smithy rules engine Language and traits"
+
+ext {
+ displayName = "Smithy :: Rules Engine"
+ moduleName = "software.amazon.smithy.rulesengine"
+}
+
+dependencies {
+ api project(":smithy-model")
+ api project(":smithy-utils")
+}
diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/package-info.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/package-info.java
new file mode 100644
index 00000000000..e39243df030
--- /dev/null
+++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/**
+ * Smithy Rules Engine.
+ */
+@SmithyUnstableApi
+package software.amazon.smithy.rulesengine;
+
+import software.amazon.smithy.utils.SmithyUnstableApi;
diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ClientContextParamDefinition.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ClientContextParamDefinition.java
new file mode 100644
index 00000000000..594f10524d7
--- /dev/null
+++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ClientContextParamDefinition.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.smithy.rulesengine.traits;
+
+import java.util.Objects;
+import java.util.Optional;
+import software.amazon.smithy.model.shapes.ShapeType;
+import software.amazon.smithy.utils.SmithyBuilder;
+import software.amazon.smithy.utils.SmithyUnstableApi;
+import software.amazon.smithy.utils.ToSmithyBuilder;
+
+/**
+ * A service client context parameter definition.
+ */
+@SmithyUnstableApi
+public final class ClientContextParamDefinition implements ToSmithyBuilder {
+ private final ShapeType type;
+ private final String documentation;
+
+ private ClientContextParamDefinition(Builder builder) {
+ this.type = SmithyBuilder.requiredState("type", builder.type);
+ this.documentation = builder.documentation;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public ShapeType getType() {
+ return type;
+ }
+
+ public Optional getDocumentation() {
+ return Optional.ofNullable(documentation);
+ }
+
+ public Builder toBuilder() {
+ return builder()
+ .type(type)
+ .documentation(documentation);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getType(), getDocumentation());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ClientContextParamDefinition that = (ClientContextParamDefinition) o;
+ return getType() == that.getType() && Objects.equals(getDocumentation(), that.getDocumentation());
+ }
+
+ public static final class Builder implements SmithyBuilder {
+ private ShapeType type;
+ private String documentation;
+
+ private Builder() {
+ }
+
+ public Builder type(ShapeType type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder documentation(String documentation) {
+ this.documentation = documentation;
+ return this;
+ }
+
+ public ClientContextParamDefinition build() {
+ return new ClientContextParamDefinition(this);
+ }
+ }
+}
diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ClientContextParamsTrait.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ClientContextParamsTrait.java
new file mode 100644
index 00000000000..f61533e70d1
--- /dev/null
+++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/traits/ClientContextParamsTrait.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.smithy.rulesengine.traits;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import software.amazon.smithy.model.node.Node;
+import software.amazon.smithy.model.node.NodeMapper;
+import software.amazon.smithy.model.shapes.ShapeId;
+import software.amazon.smithy.model.traits.AbstractTrait;
+import software.amazon.smithy.model.traits.AbstractTraitBuilder;
+import software.amazon.smithy.model.traits.Trait;
+import software.amazon.smithy.utils.BuilderRef;
+import software.amazon.smithy.utils.SmithyBuilder;
+import software.amazon.smithy.utils.SmithyUnstableApi;
+import software.amazon.smithy.utils.ToSmithyBuilder;
+
+/**
+ * Indicates that the named rule-set parameters that should be configurable
+ * on the service client using the specified smithy types.
+ */
+@SmithyUnstableApi
+public final class ClientContextParamsTrait extends AbstractTrait implements ToSmithyBuilder {
+ public static final ShapeId ID = ShapeId.from("smithy.rules#clientContextParams");
+
+ private final Map parameters;
+
+ public ClientContextParamsTrait(Builder builder) {
+ super(ID, builder.getSourceLocation());
+ this.parameters = builder.parameters.copy();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Map getParameters() {
+ return parameters;
+ }
+
+ @Override
+ protected Node createNode() {
+ NodeMapper mapper = new NodeMapper();
+ return mapper.serialize(this.getParameters()).expectObjectNode();
+ }
+
+ @Override
+ public SmithyBuilder toBuilder() {
+ return builder()
+ .sourceLocation(getSourceLocation())
+ .parameters(getParameters());
+ }
+
+ public static final class Provider extends AbstractTrait.Provider {
+ public Provider() {
+ super(ID);
+ }
+
+ @Override
+ public Trait createTrait(ShapeId target, Node value) {
+ NodeMapper mapper = new NodeMapper();
+
+ Map parameters = new LinkedHashMap<>();
+ value.expectObjectNode().getMembers().forEach((stringNode, node) -> {
+ parameters.put(stringNode.getValue(), mapper.deserialize(node, ClientContextParamDefinition.class));
+ });
+
+ ClientContextParamsTrait trait = builder()
+ .parameters(parameters)
+ .sourceLocation(value)
+ .build();
+ trait.setNodeCache(value);
+ return trait;
+ }
+ }
+
+ public static final class Builder extends AbstractTraitBuilder {
+ private final BuilderRef