Skip to content

content(what-is): rewrite the ec2 stop-instances with dynamic credentials guide#19266

Draft
alexleventer wants to merge 1 commit into
masterfrom
aleventer/run-ec2-stop-rewrite
Draft

content(what-is): rewrite the ec2 stop-instances with dynamic credentials guide#19266
alexleventer wants to merge 1 commit into
masterfrom
aleventer/run-ec2-stop-rewrite

Conversation

@alexleventer
Copy link
Copy Markdown
Contributor

Summary

Rewrites content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md for SEO and AEO. The page now opens with a quotable, prereqs-aware framing, walks through a tight numbered setup, and resolves doubts in a focused FAQ. Pulumi ESC + OIDC is the throughline.

What changed

  • Quotable opening stating exactly what the guide does and why dynamic credentials beat static keys, plus the prereqs.
  • "In this article" bullets for scannability.
  • Why dynamic credentials beat static AWS keys section — five concrete reasons, including tag-scoped least privilege for state-changing actions.
  • Prerequisites section — Pulumi Cloud, ESC CLI, AWS IAM role with OIDC trust, ec2:StopInstances + ec2:DescribeInstances.
  • Numbered setup steps with the aws-login ESC YAML and a sanity-check aws configure list.
  • The aws ec2 stop-instances invocation with flag-by-flag explanation, plus --hibernate and --force callouts and a wait instance-stopped follow-up.
  • Verification via aws sts get-caller-identity showing the assumed-role principal.
  • Common-errors tableAccessDenied, UnauthorizedOperation, IncorrectInstanceState, InvalidClientTokenId, ExpiredToken, Unable to locate credentials.
  • FAQ — nightly shutdown use case, minimum IAM with a tag-scoped policy example, multi-account, multi-region, aws-vault comparison, session duration.
  • Cross-links to /product/esc/, the AWS OIDC guide, sibling start/describe pages, sts, and resolve-* error pages.
  • Stronger meta_desc that leads with the value prop.

Test plan

  • make serve; visit /what-is/run-aws-ec2-stop-instances-with-dynamic-credentials/ and confirm the headings, code blocks, table, and cross-links render
  • Spot-check cross-links (/product/esc/, /docs/esc/guides/configuring-oidc/aws/, sibling run-aws-* pages, resolve-* pages)
  • CI lint + pinned review

🤖 Generated with Claude Code

…ials guide

Rewrite for SEO and AEO: quotable opening, semantic chunking,
numbered setup steps, common-errors table, FAQ targeting
doubt-removers, and cross-links to Pulumi ESC and related guides.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added review:triaging Claude Triage is currently classifying the PR domain:docs PR touches technical docs review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Pre-merge Review — Last updated 2026-05-20T16:50:38Z

Tip

Summary: This PR rewrites the /what-is/run-aws-ec2-stop-instances-with-dynamic-credentials/ page — a member of the dynamic-credentials family alongside the existing start-instances, describe-instances, and sts get-caller-identity what-is guides. Two factual blockers need attention before merging: the description of the aws ec2 stop-instances --force flag (the AWS reference says it attempts a graceful shutdown first and only forces if that fails within the timeout, not "without a graceful shutdown") and a precision slip in the aws-vault comparison ("no key is ever issued to a developer or runner" — but the doc itself shows short-lived STS keys are injected as env vars, so the claim should be scoped to long-lived keys). External claim verification, frontmatter sweep, temporal-trigger sweep, code-examples checks, and a style pass all ran; the verification step rate-limited on a handful of internal Pulumi capability and link claims, which are flagged as low-confidence rather than blockers.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts MEDIUM Verification rate-limited on 7 of 39 claims (Pulumi-internal capabilities + 3 link references); the two blockers are well-evidenced.
code correctness HIGH
Investigation log
  • Cross-sibling reads: not run (not in a templated section)
  • External claim verification: 24 of 39 claims verified (8 unverifiable, 2 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 24 Pass 1, 0 Pass 2, 15 Pass 3 (verified 11, contradicted 1, unverifiable 3).
  • Cited-claim spot-checks: not run (no cited claims)
  • Frontmatter sweep: ran on body + meta_desc
  • Temporal-trigger sweep: ran (recency words present in diff; spot-check in-review)
  • Code execution: not run (no static/programs/ change)
  • Code-examples checks: ran (3 specialists: structural, existence, body-code-coverage); 0 findings
  • Editorial-balance pass: not run (not under content/blog/)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
2 14 0 0

🔍 Verification trail

39 claims extracted · 24 verified · 8 unverifiable · 2 contradicted
  • L3 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Pulumi ESC brokers short-lived, OIDC-scoped credentials for running 'aws ec2 stop-instances', eliminating the need for static AWS keys." → ✅ verified (evidence: The file's meta_desc (L3) reads: "Stop EC2 instances with 'aws ec2 stop-instances' using short-lived, OIDC-scoped credentials brokered by Pulumi ESC. No static keys, fully auditable." The body further confirms: "fn::open::aws-login provide…; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md)
  • L10 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Using Pulumi ESC for dynamic AWS credentials requires the Pulumi CLI, the ESC CLI, a Pulumi Cloud account, and an AWS IAM role configured to trust Pulumi as an…" → ✅ verified (evidence: The file at L10 states verbatim: "You'll need the Pulumi CLI, the esc CLI, a Pulumi Cloud account, and an AWS IAM role configured to trust Pulumi as an OIDC provider." This matches the claim exactly.; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md)
  • L14 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- Why dynamic credentials beat static AWS keys for state-changing EC2 calls" → ➖ not-a-claim (evidence: The line is a bullet in the PR author's own document describing what their article will cover — a faithful description of the author's own content design, not a third-party-attributed assertion. The underlying security premise (dynamic/tem…; source: https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_identities_unique.html)
  • L22 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "## Why dynamic credentials beat static AWS keys" → ➖ not-a-claim (evidence: The text "## Why dynamic credentials beat static AWS keys" is a markdown section heading in the PR author's own document. It is a structural/editorial label describing the author's own content design, not a falsifiable factual assertion ab…; source: content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md, L22)
  • L24 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- No aws_access_key_id on disk. Nothing to leak from ~/.aws/credentials, a developer laptop, a CI runner cache, or a screenshot in Slack." → ➖ not-a-claim (evidence: The statement is the PR author's own editorial description of the security benefit of their dynamic-credentials design — enumerating leak vectors (laptop, CI cache, Slack screenshot) as motivation. It is not a falsifiable third-party-attri…; source: https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)
  • L26 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "AWS STS sessions obtained via Pulumi ESC expire based on the 'duration' configured, with a default of 1 hour." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L27 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Every StopInstances CloudTrail event carries the assumed-role principal and a session name." → ✅ verified (framing: strengthened — claim narrows the general CloudTrail AssumedRole behavior to 'StopInstances events specifically'; source's broader form (all API calls made with…; evidence: AWS CloudTrail's userIdentity element for AssumedRole calls includes the assumed-role principal and session name. Per AWS docs, "for requests made with temporary security credentials, this value includes the session name that is passed to…; source: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)
  • L32 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- A Pulumi Cloud account and an organization you can create environments in." → ➖ not-a-claim (evidence: The text is a prerequisite bullet point linking to the Pulumi Cloud sign-in page (https://app.pulumi.com/signin). It is a navigational/reference link, not a falsifiable factual assertion about Pulumi's capabilities or behavior.; source: content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md L32)
  • L33 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- The Pulumi CLI and the ESC CLI installed and authenticated (esc login)." → ✅ verified (evidence: The path /docs/install/esc/ is a confirmed alias for content/docs/esc/cli/download-install/_index.md in the pulumi/docs repo, and is used extensively as the canonical ESC CLI installation link across many docs pages.; source: gh search code --owner pulumi "install/esc" (pulumi/docs:content/docs/esc/cli/download-install/_index.md shows - /docs/install/esc/ as an alias))
  • L35 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The IAM role used with Pulumi ESC for stopping EC2 instances requires 'ec2:StopInstances' and 'ec2:DescribeInstances' permissions, and a trust policy that allo…" → ✅ verified (evidence: The file at line 35 explicitly states: "An IAM role with ec2:StopInstances and ec2:DescribeInstances, and a trust policy that allows Pulumi's OIDC issuer to assume it." The referenced OIDC guide confirms the trust policy uses Pulumi's…; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md (L35) and repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L36 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The AWS CLI v2 is required as a prerequisite for this workflow." → ✅ verified (evidence: The Prerequisites section of the file explicitly lists "The AWS CLI v2 installed." as a required prerequisite bullet point, directly confirming the claim.; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md)
  • L43 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Follow the configuring OIDC between Pulumi and AWS guide to create an IAM role whose trust policy accepts Pulumi's OI…" → ✅ verified (evidence: The file at content/docs/esc/guides/configuring-oidc/aws.md exists and covers exactly what the claim describes: creating an IAM role whose trust policy accepts Pulumi's OIDC issuer, and noting the ARN — "Before you log out of the AWS con…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L70 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The fn::open::aws-login provider performs the AssumeRoleWithWebIdentity call against AWS STS at runtime." → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)
  • L70 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The 'environmentVariables' block in a Pulumi ESC environment exposes the resulting short-lived credentials to any process 'esc run' invokes." → ✅ verified (evidence: The file itself at the described location contains the exact claim: "The environmentVariables block exposes the resulting short-lived credentials to any process esc run invokes." This accurately describes the core ESC behavior where th…; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md)
  • L97 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "esc run <env> -- opens the named ESC environment, assumes the IAM role, and injects the short-lived credentials as environment variables for the command that…" → ✅ verified (framing: strengthened — the source describes the general environmentVariables injection mechanism; the claim correctly narrows it to the specific AWS OIDC/IAM role cred…; evidence: The official esc run CLI docs state: "This command opens the environment with the given name and runs the given command. If the opened environment contains a top-level 'environmentVariables' object, each key-value pair in the object is m…; source: repo:content/docs/esc/cli/commands/esc_run.md)
  • L98 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The '--instance-ids' flag for 'aws ec2 stop-instances' accepts a space-separated list of instance IDs." → ✅ verified (evidence: The AWS CLI shorthand syntax docs explicitly show: "aws ec2 stop-instances \ --instance-ids i-1486157a i-1286157c i-ec3a7e87" — a space-separated list of instance IDs passed to --instance-ids.; source: https://docs.aws.amazon.com/cli/v1/userguide/cli-usage-shorthand.html)
  • L99 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "EC2 is region-scoped, so instance IDs must live in the region you query with --region." → ✅ verified (evidence: AWS official docs confirm: "The ID of an instance is tied to the Region for the instance, and can only be used in this Region." This directly supports the claim that EC2 is region-scoped and instance IDs must live in the region you query.; source: https://docs.aws.amazon.com/ec2/latest/instancetypes/ec2-instance-regions.html)
  • L100-101 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The '--hibernate' flag for 'aws ec2 stop-instances' stops instances by hibernating them rather than shutting them down, if they were launched with hibernation…" → ✅ verified (evidence: The AWS EC2 API Reference confirms: "Hibernates the instance if the instance was enabled for hibernation at launch. If the instance cannot hibernate successfully, a normal shutdown occurs." The AWS CLI docs and user guide confirm `--hibern…; source: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_StopInstances.html)
  • L101 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The --force flag forces an EC2 instance stop without a graceful shutdown." → ❌ contradicted (framing: shifted — claim says --force stops "without a graceful shutdown"; source says it first attempts a graceful shutdown and only bypasses it if that fails within t…; evidence: The official AWS CLI reference states: "Forces the instance to stop. The instance will first attempt a graceful shutdown, which includes flushing file system caches and metadata." Only if that graceful shutdown fails within the timeout doe…; source: https://docs.aws.amazon.com/cli/latest/reference/ec2/stop-instances.html)
  • L110 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "A successful 'aws ec2 stop-instances' response includes a 'StoppingInstances' array with 'InstanceId', 'CurrentState', and 'PreviousState' fields, where the st…" → ✅ verified (evidence: AWS CLI and Boto3 docs confirm the exact response shape and codes: "StoppingInstances": [{"InstanceId": "...", "CurrentState": {"Code": 64, "Name": "stopping"}, "PreviousState": {"Code": 16, "Name": "running"}}]. Boto3 docs also list all s…; source: https://docs.aws.amazon.com/cli/latest/reference/ec2/stop-instances.html; https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2/client/stop_instances.html)
  • L135 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "'Arn': 'arn:aws:sts::123456789012:assumed-role/pulumi-esc-oidc/pulumi-environments-session'" → ➖ not-a-claim (evidence: The ARN arn:aws:sts::123456789012:assumed-role/pulumi-esc-oidc/pulumi-environments-session appears in a sample aws sts get-caller-identity output block in the documentation, using the canonical AWS placeholder account ID 123456789012…; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md)
  • L139 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The matching CloudTrail StopInstances event will show userIdentity.type = AssumedRole and the same session name when dynamic credentials are used." → ✅ verified (framing: strengthened — claim narrows the general AWS CloudTrail AssumedRole behavior to the specific StopInstances event with dynamic credentials; source's broader for…; evidence: AWS CloudTrail docs confirm: "AssumedRole – The request was made with temporary security credentials that were obtained with a role by making a call to the AWS Security Token Service (AWS STS) AssumeRole API." For temporary credentials, "t…; source: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)
  • L145 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "| AccessDenied: not authorized to perform: sts:AssumeRoleWithWebIdentity | IAM role trust policy does not allow Pulumi's OIDC issuer or your org's audience |…" → ✅ verified (evidence: The file content/docs/esc/guides/configuring-oidc/aws.md exists and is a guide titled "Configuring OpenID Connect for AWS" that covers IAM role trust policies and sts:AssumeRoleWithWebIdentity, directly matching the linked guide refere…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L148 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "| InvalidClientTokenId | The ESC env didn't inject credentials; you're hitting AWS with stale or empty keys | Confirm the environmentVariables block and th…" → ✅ verified (evidence: The file content/what-is/resolve-list-buckets-invalid-client-token-id.md exists in the repo and covers exactly the topic referenced: resolving InvalidClientTokenId errors when calling AWS operations (like ListBuckets) by using Pulumi E…; source: repo:content/what-is/resolve-list-buckets-invalid-client-token-id.md)
  • L149-150 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "| Unable to locate credentials | esc run was not used and no other AWS credential source is configured | Wrap the command in esc run <env> -- ([more](/wh…" → ✅ verified (evidence: The file content/what-is/resolve-unable-to-locate-credentials.md exists and its page title is "Unable to locate credentials", matching the error message in the claim. The page describes using esc run to resolve this error, consistent w…; source: repo:content/what-is/resolve-unable-to-locate-credentials.md)
  • L156 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Pulumi's GitHub Actions, GitLab CI, and CircleCI integrations all support the esc run pattern for CI use." → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)
  • L160 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The minimum IAM permissions required for the role are 'ec2:StopInstances' for the stop action and 'ec2:DescribeInstances' so the CLI can resolve and validate t…" → ✅ verified (framing: strengthened — AWS docs confirm ec2:StopInstances + ec2:DescribeInstances as the standard permission pair; the claim's stated reason for DescribeInstances ("re…; evidence: AWS IAM documentation examples consistently pair ec2:StopInstances with ec2:DescribeInstances for stop-instance workflows. The official IAM docs show a policy with "ec2:StopInstances" and "ec2:DescribeInstances" together as the req…; source: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_ec2_tag-owner.html)
  • L166 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "'Resource': 'arn:aws:ec2:::instance/'," → ✅ verified (evidence: AWS documentation and official sources confirm the EC2 instance ARN format is arn:aws:ec2:region:account:instance/*. Using wildcards for region and account is valid in IAM policy Resource elements; arn:aws:ec2:*:*:instance/* is a stand…; source: https://aws.amazon.com/blogs/security/demystifying-ec2-resource-level-permissions/ — "You specify the resource using an Amazon Resource Name (ARN) in a format like arn:aws:ec2:region:account:instance/")
  • L173 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Pulumi ESC supports environment imports to compose a base environment with account-specific overrides for multi-account AWS setups." → ✅ verified (framing: strengthened — claim narrows the general "compose environments" capability to the specific multi-account AWS use case; source's broader form proves the claim a…; evidence: The imports page states: "Pulumi ESC allows you to compose environments by importing configuration and secrets from other environments. This reduces duplication, ensures consistency, and enables you to organize configuration hierarchically…; source: content/docs/esc/environments/imports.md)
  • L177 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "aws ec2 stop-instances is a single-region call and cannot stop instances in multiple regions in one command." → ✅ verified (framing: strengthened — the source's broader statement ("run a command in each Region") implies the single-region-per-call constraint; the claim correctly narrows this…; evidence: The AWS EC2 CLI stop-instances command accepts only a single --region flag (overriding config/env for one region per invocation). The official AWS docs confirm the regional scope: "Alternatively, you can run a command or cmdlet in each…; source: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Stop_Start.html)
  • L177 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The IAM role is assumed once per esc run invocation." → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)
  • L185 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "aws-vault stores long-lived keys in the OS keychain and brokers temporary sessions locally." → ✅ verified (framing: strengthened — claim narrows 'generates temporary credentials from those to expose to your shell and applications' to 'brokers temporary sessions locally'; sou…; evidence: The official aws-vault README states: "AWS Vault stores IAM credentials in your operating system's secure keystore and then generates temporary credentials from those to expose to your shell and applications." This confirms both storing lo…; source: https://github.com/99designs/aws-vault)
  • L185 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Pulumi ESC removes the long-lived key entirely: the trust is OIDC-based and lives in IAM, so no key is ever issued to a developer or runner." → ❌ contradicted (framing: shifted — claim says "no key is ever issued to a developer or runner" but the source shows short-lived STS keys (accessKeyId/secretAccessKey/sessionToken) are…; evidence: The file itself shows that ESC does inject short-lived STS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) into the runner process via the environmentVariables block — so keys are issued to the runner,…; source: repo:content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md — environmentVariables: AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId} AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey} AWS_SESSION_TOKEN: ${aws.login.sessionToken})
  • L185 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "Pulumi ESC provides centralized environments, secret aggregation from other providers, and audit logs across the team, unlike aws-vault." → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)
  • L189 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "The 'duration' field in the 'aws-login' block requests the session duration; AWS enforces the MaxSessionDuration cap." → ✅ verified (evidence: AWS STS confirms that when calling AssumeRole, the DurationSeconds parameter requests the session duration, and "this API call will fail if you request a session duration longer than is configured on the role itself (in the 'max session du…; source: https://awsteele.com/blog/2024/08/05/surprising-behaviour-in-aws-web-console-session-duration.html; https://repost.aws/knowledge-center/iam-role-chaining-limit)
  • L193-194 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- Configuring OIDC between Pulumi and AWS" → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)
  • L195 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- esc run command reference" → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)
  • L197-199 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- Run aws sts get-caller-identity with dynamic credentials" → ✅ verified (evidence: The file content/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials.md exists in the repo with the title "Run 'aws sts get-caller-identity' using Dynamic Credentials", confirming the linked page at `/what-is/run-aws-sts-get…; source: repo:content/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials.md)
  • L200 in content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md "- Related error resolution: InvalidClientTokenId, [ExpiredToken](/what-is/resolve-list-buckets-ex…" → 🤷 unverifiable (evidence: verify-claims.py errored on this claim: RuntimeError: HTTP 429: {"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 2,000,000 input tokens per minute (org: 85d1a054-3697…)

Claim verification reported errors — some verdicts may be incomplete; spot-check the affected claims in-review.

🚨 Outstanding in this PR

These must be resolved or refuted before merging.

  • [L101] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"--force (optional, dangerous) forces stop without a graceful shutdown — use only if a normal stop is stuck." — ❌ contradicted by the AWS stop-instances CLI reference, which says --force first attempts a graceful shutdown and only bypasses it if the shutdown does not complete within the timeout. Suggest:

    --force (optional, dangerous) attempts a graceful shutdown first and only forces the stop if the shutdown doesn't complete within the timeout — use only if a normal stop is stuck.

  • [L185] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"Pulumi ESC removes the long-lived key entirely: the trust is OIDC-based and lives in IAM, so no key is ever issued to a developer or runner." — ❌ contradicted by the document itself: the environmentVariables block at L65–67 injects short-lived AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN into the runner for each esc run invocation, so keys are issued — just short-lived ones. The contrast with aws-vault is "no long-lived key," not "no key at all." Suggest:

    Pulumi ESC removes the long-lived key entirely: the trust is OIDC-based and lives in IAM, so no long-lived AWS credentials sit on a developer machine or CI runner. (Short-lived STS credentials are still injected as environment variables for the duration of each esc run invocation, then discarded.)

⚠️ Low-confidence

Review each and resolve as appropriate — these don't block the PR.

  • [L26] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"Sessions expire on the duration you configure (default 1 hour)." — 🤷 verification didn't converge. The related claim at L189 about the aws-login duration field and AWS's MaxSessionDuration cap is ✅ verified, and 1 hour is the standard AWS STS AssumeRole default — but please double-check that ESC's aws-login provider also defaults to 1 hour when duration is omitted (rather than inheriting the role's MaxSessionDuration).

  • [L70] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"The fn::open::aws-login provider performs the AssumeRoleWithWebIdentity call against AWS STS at runtime." — 🤷 verification rate-limited before completing. This is a Pulumi-internal capability claim and matches what the aws-login provider documents, but please confirm against the aws-login provider reference that AssumeRoleWithWebIdentity (and not AssumeRole) is the API the OIDC code path invokes.

  • [L156] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"Pulumi's GitHub Actions, GitLab CI, and CircleCI integrations all support this pattern." — 🤷 verification rate-limited before completing. Pulumi publishes first-party integrations for each of the three, but an author confirmation that all three currently support invoking esc run (versus, say, an SDK-style auth flow only) would close this out — or a link to the CI-integrations index would let a reader self-verify.

  • [L177] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"The role is assumed once per esc run." — 🤷 verification rate-limited before completing. This is a Pulumi-internal capability claim about ESC environment opening; consistent with how esc run is documented elsewhere but please confirm: is the role re-assumed if a single esc run invocation outlives the session duration, or does the command simply error out?

  • [L185] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"ESC also gives you centralized environments, secret aggregation from other providers, and audit logs across the team." — 🤷 verification rate-limited before completing. Each of these is a documented Pulumi ESC feature (centralized environments, multi-provider secret import, org-level audit logs), so this is most likely an artifact of the rate-limit interruption rather than a real defect — but please double-check that the comparison still reads accurately at the line level.

  • [L193-194] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"Configuring OIDC between Pulumi and AWS" — 🤷 verification rate-limited before completing. The same /docs/esc/guides/configuring-oidc/aws/ link is ✅ verified at L43 of this same trail (the target page exists at content/docs/esc/guides/configuring-oidc/aws.md), so this Learn-more link is fine — no action needed from the author.

  • [L195] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"esc run command reference" — 🤷 verification rate-limited before completing. The target page exists at content/docs/esc/cli/commands/esc_run.md and is the source the L97 (esc run behavior) verification already drew on, so this Learn-more link is fine — no action needed from the author.

  • [L200] content/what-is/run-aws-ec2-stop-instances-with-dynamic-credentials.md"Related error resolution: InvalidClientTokenId, ExpiredToken, Unable to locate credentials" — 🤷 verification rate-limited before completing. The first and third targets are ✅ verified at L148 and L149-150 of this same trail; the middle target (/what-is/resolve-list-buckets-expired-token/) was not explicitly checked but the corresponding content/what-is/resolve-list-buckets-expired-token.md page exists, so all three Learn-more links are fine.

Style findings

Found by pattern-based linting; Findings may be false positives.

  • line 148: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 149: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 150: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 154: [style] first person — Avoid first-person pronouns such as ' I '.
  • line 175: [style] first person — Avoid first-person pronouns such as ' I '.
  • line 179: [style] first person — Avoid first-person pronouns such as ' I '.

💡 Pre-existing issues in touched files (optional)

No pre-existing issues in touched files.

✅ Resolved since last review

No items resolved since the last review.

📜 Review history

  • 2026-05-20T16:50:38Z — Initial review: 2 contradicted claims to address (--force description; "no key is ever issued" overclaim against aws-vault), 7 capability/link claims rate-limited during verification but not blockers. (bdd19fe)

Need a re-review? Want to dispute a finding? Mention @claude and include #update-review.
(For ad-hoc questions or fixes, just @claude — no hashtag.)

@github-actions github-actions Bot added review:outstanding-issues Claude review completed; outstanding has author-actionable findings and removed review:in-progress Claude review is currently running labels May 20, 2026
@pulumi-bot
Copy link
Copy Markdown
Collaborator

@alexleventer alexleventer marked this pull request as draft May 20, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:docs PR touches technical docs review:outstanding-issues Claude review completed; outstanding has author-actionable findings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants