diff --git a/docs/docs/40-operator-guide/40-security/60-promotion-pod-identity.md b/docs/docs/40-operator-guide/40-security/60-promotion-pod-identity.md
new file mode 100644
index 0000000000..8bb75e89a1
--- /dev/null
+++ b/docs/docs/40-operator-guide/40-security/60-promotion-pod-identity.md
@@ -0,0 +1,142 @@
+---
+description: Learn how to set up workload identity for promotion pods
+sidebar_label: Promotion Pod Identity
+---
+
+
+
+
+:::info
+
+This document describes how to set workload identity for promotions run by
+Promotion Controller in Kargo versions v1.11 and above.
+
+Promotion Controller is only available in Kargo on the [Akuity Platform](https://akuity.io/akuity-platform)
+and requires use of self-hosted agent.
+
+:::
+
+# Promotion Pod identity
+
+## Background
+
+Most workload identity tools are using pod serviceaccounts to provision access for tools running in the pod.
+
+When using Promotion Controller, each promotion is run as a pod with steps running as containers in this pod.
+This makes it possible for steps to access workload identity for the promotion pod and have required permissions.
+
+Promotion pods are assigned `kargo-promotion-orchestrator` serviceaccount by default.
+While it is technically possible to assign federated identity (e.g. IRSA) to `kargo-promotion-orchestrator`
+serviceaccount, Akuity Platform may override these setting for example when upgrading or configuring Kargo.
+
+Also using the same serviceaccount to access multiple different roles for different promotions/stages/steps is not the
+best approach from security or configuration point of view.
+
+## Promotion decorator annotation for Stages
+
+Since version `1.11`, Kargo supports decorator annotations for `Stage` resources, which will change how
+Promotion Controller runs promotion pods.
+
+Supported decorator annotations are:
+
+- `ee.kargo.akuity.io/promotion-sa` - **overrides** the serviceaccount used to run the promotion pod
+- `ee.kargo.akuity.io/promotion-labels` - **extends** the labels used in the promotion pod
+- `ee.kargo.akuity.io/promotion-annotations` - **extends** the annotations used in the promotion pod
+
+Each annotation can be set separately. Empty values have no effect.
+
+:::warning
+
+If not empty, `promotion-sa` must be a valid serviceaccount in the agent namespace.
+`promotion-labels` must be a JSON string with valid k8s labels.
+`promotion-annotations` must be a JSON string with valid k8s annotations.
+
+Promotion will error if values in these annotations are invalid.
+
+:::
+
+## Example using decorators for a stage
+
+For example if we have a custom step accessing S3:
+
+```
+apiVersion: ee.kargo.akuity.io/v1alpha1
+kind: CustomPromotionStep
+metadata:
+ name: aws-s3-ls
+spec:
+ image: amazon/aws-cli
+ command: [
+ "sh",
+ "-c",
+ "mkdir -p $HOME; aws s3 ls s3://{{ config.bucket }}"]
+ env:
+ - name: HOME ## HOME is required to run as non-root
+ value: /tmp/home
+```
+
+And we have a serviceaccount configured to access a role with S3 access:
+```
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ annotations:
+ eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/access-s3
+ labels:
+ app.kubernetes.io/managed-by: eksctl
+ name: s3-access
+ namespace: akuity
+```
+
+We can configure a stage to use this serviceaccount and access the role:
+
+```
+apiVersion: kargo.akuity.io/v1alpha1
+kind: Stage
+metadata:
+ name: my-stage
+ namespace: kargo-demo
+ annotations:
+ ee.kargo.akuity.io/promotion-sa: s3-access
+spec:
+ promotionTemplate:
+ spec:
+ steps:
+ - as: list s3
+ config:
+ bucket: my_bucket_name
+ uses: aws-s3-ls
+ requestedFreight:
+ ...
+```
+
+## Known limitations
+
+Because entire promotion is running in a single pod, all steps in the pod will have the same identity and will get the same
+access provisioned into them.
+
+This means steps within the same promotion cannot use different serviceaccounts. If they need different permissions, those
+need to be attached to the same serviceaccount.
+
+Some builtin steps require serviceaccount to have specific k8s role bindings.
+Namely when running `argocd-update` with incluster ArgoCD (on the same cluster as promotion controller agent),
+the serviceaccount used in promotion must be bound to `kargo-promotion-token-manager` role.
+
+You can create a binding for serviceaccount like this:
+```
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: kargo-promotion-token-manager-orchestrator
+ namespace: akuity ## Promotion namespace
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "kargo-promotion-token-manager"
+subjects:
+ - kind: ServiceAccount
+ namespace: akuity ## Promotion namespace
+ name:
+```
+
+**NOTE** this only applies to a setup where ArgoCD runs in the same cluster as promotion pods.
\ No newline at end of file
diff --git a/docs/docs/50-user-guide/60-reference-docs/70-annotations.md b/docs/docs/50-user-guide/60-reference-docs/70-annotations.md
index 3e2a6f4642..8c3e4dcd27 100644
--- a/docs/docs/50-user-guide/60-reference-docs/70-annotations.md
+++ b/docs/docs/50-user-guide/60-reference-docs/70-annotations.md
@@ -27,6 +27,9 @@ programmatically with Kargo.
| `rbac.kargo.akuity.io/managed` | `ServiceAccount`, `Role`, `RoleBinding` | `"true"` | Permits the UI or CLI (via the API server) to programmatically manage trios of `ServiceAccount`, `Role`, and `RoleBinding` resources via Kargo's own ["roles" abstraction](../50-security/20-access-controls/index.md#managing-mappings-and-permissions). Omit this annotation if you wish to exclusively manage these resources [declaratively](../50-security/20-access-controls/index.md#managing-kargo-roles-declaratively). |
| `kargo.akuity.io/replicate-to` | `Secret`, `ConfigMap` (in the shared resources namespace) | `"*"` | Enables automatic replication of the resource to all Project namespaces. For more details, see the [Replicating Shared Resources](../../40-operator-guide/40-security/40-managing-secrets.md#replicating-shared-resources-to-project-namespaces) section of the Operator Guide. |
| `kargo.akuity.io/replicated-at` | `Secret`, `ConfigMap` (replicated copies) | UTC timestamp | Records when the resource was last replicated from the source. Managed by the system. |
+| `ee.kargo.akuity.io/promotion-sa` | `Stage` | String `ServiceAccount` name in promotion namespace | Overrides default serviceaccount for promotion pods ran by Promotion Controller (Kargo EE only) |
+| `ee.kargo.akuity.io/promotion-labels` | `Stage` | JSON string encoding valid K8s labels | Extends labels for promotion pods ran by Promotion Controller (Kargo EE only) |
+| `ee.kargo.akuity.io/promotion-annotations` | `Stage` | JSON string encoding valid K8s annotations | Extends annotations for promotion pods ran by Promotion Controller (Kargo EE only) |
## Labels