Skip to content

Document the default policy groups - #20563

Merged
jkodroff merged 2 commits into
masterfrom
jkodroff/default-policy-groups
Jul 29, 2026
Merged

Document the default policy groups#20563
jkodroff merged 2 commits into
masterfrom
jkodroff/default-policy-groups

Conversation

@jkodroff

Copy link
Copy Markdown
Member

Documents the two policy groups every organization gets automatically, and the policy pack runtime requirements that were previously undocumented.

Fixes #20554

Changes

  • Default policy groups: new section on /docs/insights/policy/policy-groups/ covering both groups, automatic membership, which properties are immutable, and the blast radius of adding a pack to the default preventative group.
  • Name correction: the page named default-preventative-policy-group and default-audit-policy-group. Neither exists. Verified against four live orgs and pulumi-service (cmd/service/model/policy_groups.go): the real names are default-policy-group (stacks, preventative) and default-accounts-policy-group (accounts, audit). Also fixed on the discovery and policy get-started pages.
  • Runtime requirements: new section on /docs/insights/policy/policy-packs/. The pack's runtime, not the program's language, decides what the client needs. All 28 Pulumi pre-built packs are runtime: nodejs, and Bun does not substitute. Cross-referenced from the CI/CD, CLI, and plugins pages.
  • Structure and tone: merged the comparison table into Types, consolidated guidance under Best practices (type choice, enforcement levels, adoption path), and reduced the marketing voice on the policy packs page.

Follow-ups (not in this PR)

  • Upstream pulumi-service spec PR: PATCH .../policygroups/{policyGroup} doesn't document that newName is rejected on default groups, or that a group's type is set at creation only.
  • Whether Pulumi Cloud accepts runtime: bun on publish is unverified server-side, so project-file.md still lists only nodejs/python/opa.

Adds a "Default policy groups" section covering the two groups every
organization gets, what can and cannot be changed about them, and the
blast radius of adding a policy pack to the default preventative group.

Corrects the group names, which were wrong. The real names are
default-policy-group (stacks, preventative) and
default-accounts-policy-group (accounts, audit).

Also documents policy pack runtime requirements, which were previously
undocumented: the pack's runtime, not the program's language, determines
what the client needs, and every Pulumi pre-built pack runs on Node.js.

Restructures both policy pages so they read top to bottom, and tones
down the marketing voice on the policy packs page.

Fixes #20554

Co-Authored-By: Claude Opus 5 (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 labels Jul 29, 2026
@jkodroff
jkodroff requested a review from CamSoper July 29, 2026 16:48
@github-actions github-actions Bot added review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels Jul 29, 2026
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Pre-merge Review — Last updated 2026-07-29T18:59:40Z

Tip

Summary: This PR expands the Insights Policy docs to document the two default policy groups (default-policy-group for preventative, default-accounts-policy-group for audit), how their membership can and cannot be changed via the REST API and the Pulumi Cloud provider, and the runtime each policy pack requires on the machine that runs Pulumi. It rewrites policy-groups.md and policy-packs/_index.md and adds cross-links from five neighboring Policy pages, paralleling the existing Insights/Policy reference set. The wrongness that would block a reader here is a mis-stated group name or management step (following it would fail to change membership) or an overstated requirement — chiefly the repeated claim that every pre-built pack runs on Node.js, which drives readers to provision Node.js everywhere. Passes run: external + repo claim verification, a repo-wide cross-sibling check for the renamed group identifiers and restructured anchors, frontmatter/alias validation, and prose linting.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts MEDIUM Previously-flagged self-contradiction fixed in b53aa3b; several REST-API / Cloud-provider behavior statements and the "pre-built packs all run on Node.js" claim remain unconfirmed against public sources — author confirmation requested.
cross-sibling consistency HIGH Old group names appear only in the rewritten page; inbound policy-groups/#… anchor links still resolve.
Investigation log
  • Cross-sibling reads: 4 of 11 siblings directly read (api-reference.md, policy-findings.md, pre-built-packs.md, project-file.md — the Policy neighborhood); a repo-wide search covered the rest for the renamed group identifiers and inbound policy-groups/#… anchor links. The iac/concepts peers are unrelated to the policy-group changes.
  • External claim verification: 63 of 73 claims verified (8 unverifiable, 0 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 63 Pass 1, 1 Pass 2 (verified 0, contradicted 0, unverifiable 1), 9 Pass 3 (verified 6, contradicted 0, unverifiable 3).
  • Cited-claim spot-checks: 1 of 1 cited claims fetched and compared
  • 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: not run (no fenced code blocks in content files)
  • Editorial-balance pass: not run (not under content/blog/)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
0 7 0 1

🔍 Verification trail

73 claims extracted · 63 verified · 8 unverifiable · 0 contradicted
  • L48 in content/docs/iac/concepts/plugins.md "Because policy packs run on the machine that runs Pulumi, that machine needs the policy pack's runtime installed." → ✅ verified (evidence: The linked page's "Runtime requirements" section states verbatim: "Policy packs run on the machine that runs Pulumi, so the pack's runtime must be installed there," matching the claim exactly.; source: repo:content/docs/insights/policy/policy-packs/_index.md#runtime-requirements)
  • L87 in content/docs/insights/discovery/get-started/add-policies.md "Selecting 'Add accounts' and typing an account name (e.g. production/us-west-2) then selecting 'Add account to policy group' adds the insights account to the p…" → ✅ verified (evidence: The claim is a direct paraphrase of the doc's own step: "Now add your insights account to the policy group. Select Add accounts and type the name of the account you want to include for Insights policies. (e.g. production/us-west-2) Finally…; source: repo:content/docs/insights/discovery/get-started/add-policies.md)
  • L90 in content/docs/insights/discovery/get-started/add-policies.md "The Pulumi documentation has a page titled 'default policy groups' at /docs/insights/policy/policy-groups/#default-policy-groups describing this default policy…" → ✅ verified (evidence: content/docs/insights/policy/policy-groups.md contains a heading "## Default policy groups" (line 38) which renders to anchor #default-policy-groups at path /docs/insights/policy/policy-groups/, matching the claimed URL, and it describes t…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L26 in content/docs/insights/policy/ci-cd.md "The CI image running a policy pack must have that policy pack's runtime installed, and this runtime is not necessarily the same runtime used by the Pulumi prog…" → ✅ verified (evidence: The cited target page (policy-packs/_index.md, "Runtime requirements" section) states: "Policy packs run on the machine that runs Pulumi, so the pack's runtime must be installed there... not the language your Pulumi program is written in.…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L54 in content/docs/insights/policy/cli.md "Pulumi Cloud users can skip the --policy-pack flag entirely because policy packs enabled through policy groups are downloaded and applied automatically." → ✅ verified (evidence: The cli.md note itself states: "Pulumi Cloud users can skip this flag entirely because policy packs enabled through [policy groups] are downloaded and applied automatically." This is corroborated by policy-groups.md describing preventative…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L87 in content/docs/insights/policy/get-started.md "The documentation includes a page/section titled 'default policy groups' at /docs/insights/policy/policy-groups/#default-policy-groups that provides more detai…" → ✅ verified (evidence: policy-groups.md contains a heading "## Default policy groups" (line 38) which yields the anchor #default-policy-groups, matching the cited link /docs/insights/policy/policy-groups/#default-policy-groups exactly, and the section content ma…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L87 in content/docs/insights/policy/get-started.md "The default audit policy group is named default-accounts-policy-group and applies to all cloud accounts." → 🤝 matches (evidence: policy-groups.md states: "default-accounts-policy-group | Audit | Every cloud account connected to Insights" and "New stacks and newly connected cloud accounts join the matching default group as they are created," confirming the name and…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L21 in content/docs/insights/policy/policy-groups.md "Pulumi Policies provides two types of policy groups, each designed for a different enforcement pattern." → ✅ verified (evidence: The live Pulumi docs page states verbatim: "Pulumi Policies provides two types of policy groups, each designed for different enforcement patterns: Preventative policy groups apply to Pulumi stacks and run before resources are deployed."; source: https://www.pulumi.com/docs/insights/policy/policy-groups/)
  • L23 in content/docs/insights/policy/policy-groups.md "Preventative policy groups act as guardrails during pulumi preview and pulumi up, evaluating the resources the Pulumi program declares and reporting violat…" → ✅ verified (evidence: The doc itself states: "Preventative policy groups apply to Pulumi stacks and run before any resource is deployed. They act as guardrails during pulumi preview and pulumi up, evaluating the resources your program declares and reporting…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L25 in content/docs/insights/policy/policy-groups.md "Audit policy groups report violations rather than blocking them, which makes them the safest place to measure a new policy's impact before enforcing it anywher…" → ✅ verified (evidence: The doc itself states verbatim: "Audit groups report violations rather than blocking them, which makes them the safest place to measure a new policy's impact before you enforce it anywhere," and this is reinforced later: "To roll out a new…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L25 in content/docs/insights/policy/policy-groups.md "For cloud accounts, audit policy groups scan on a schedule and cover every resource in the account, including resources created by hand, by another tool, or by…" → ✅ verified (evidence: The linked accounts page (content/docs/insights/discovery/accounts.md, aliased to /docs/insights/accounts/) confirms scheduled scanning: "Scans run every 24 hours; you can switch to a 12-hour schedule instead," and describes scans covering…; source: repo:content/docs/insights/discovery/accounts.md (aliased to /docs/insights/accounts/))
  • L29-34 in content/docs/insights/policy/policy-groups.md "Preventative policy groups block deployments when enforcement is set to mandatory, while audit policy groups do not block deployments and instead report find…" → ✅ verified (evidence: Pulumi docs confirm: "Preventative: Validates Pulumi stack resources during pulumi preview and pulumi up, blocking deployments when violations are detected" while "Audit: Continuously scans resources discovered through Insights Discovery t…; source: https://www.pulumi.com/docs/insights/policy/)
  • L29-34 in content/docs/insights/policy/policy-groups.md "Audit policy groups apply to Pulumi stacks and cloud accounts, run on stack updates and on a schedule for cloud accounts, see stack state plus every resource i…" → ✅ verified (evidence: The official policy-groups doc states: "Audit policy groups provide continuous compliance monitoring for both Pulumi stacks and cloud accounts. For stacks, they evaluate the latest state whenever the stack updates. For cloud accounts, they…; source: https://www.pulumi.com/docs/insights/policy/policy-groups/)
  • L40-45 in content/docs/insights/policy/policy-groups.md "The default audit policy group is named default-accounts-policy-group and every cloud account connected to Insights joins it automatically." → ✅ verified (evidence: Sibling doc content/docs/insights/discovery/get-started/add-policies.md states: "Cloud accounts are automatically added to default-accounts-policy-group, and stacks to default-policy-group, as they are created." This corroborates both…; source: repo:content/docs/insights/discovery/get-started/add-policies.md and gh api repos/pulumi/pulumi/contents/sdk/go/common/apitype/policy.go)
  • L42-45 in content/docs/insights/policy/policy-groups.md "default-accounts-policy-group is an Audit-type policy group that every cloud account connected to Insights automatically joins." → ✅ verified (evidence: The doc's own table states: default-accounts-policy-group | Audit | Every cloud account connected to Insights, and the following paragraph confirms newly connected cloud accounts join the matching default group automatically.; source: repo:content/docs/insights/policy/policy-groups.md)
  • L47 in content/docs/insights/policy/policy-groups.md "You can remove a stack or account from its default policy group at any time, the same way you would with any other policy group." → ✅ verified (evidence: The same doc states default groups are "mutable only in membership" and provides a table showing "Add or remove stacks" and "Add or remove cloud accounts" are supported via REST API (removeStack, removeInsightsAccount) and the Pulumi C…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L49 in content/docs/insights/policy/policy-groups.md "The pulumi policy enable and pulumi policy disable CLI commands act on the default policy group when the --policy-group flag is omitted." → ✅ verified (evidence: Auto-generated CLI reference for both commands states: "--policy-group string The Policy Group for which the Policy Pack will be enabled; if not specified, the default Policy Group is used" (and analogous for disable), confirming the def…; source: repo:content/docs/iac/cli/commands/pulumi_policy_enable.md, repo:content/docs/iac/cli/commands/pulumi_policy_disable.md)
  • L51 in content/docs/insights/policy/policy-groups.md "### Adding policy packs to the default preventative group" → ➖ not-a-claim (evidence: This is a markdown heading within the PR's own documentation file describing the page's own content structure, not a falsifiable third-party assertion.; source: content/docs/insights/policy/policy-groups.md L51)
  • L53-54 in content/docs/insights/policy/policy-groups.md "A policy pack added to default-policy-group takes effect on the next pulumi preview or pulumi up for every stack, and any policy set to mandatory start…" → ✅ verified (evidence: The same doc states preventative groups "act as guardrails during pulumi preview and pulumi up... a policy set to mandatory enforcement stops a non-compliant change" and that default-policy-group "contains every stack in your organ…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L54 in content/docs/insights/policy/policy-groups.md "Pulumi's pre-built policy packs all run on Node.js." → 🤷 unverifiable (evidence: The Pre-built policy packs docs page describes availability, plan tiers, and benefits of pre-built packs but does not state what runtime/language they are implemented in; other Pulumi Policy docs consistently describe policies (custom or o…; source: https://www.pulumi.com/docs/insights/policy/policy-packs/pre-built-packs/; intuition: No source directly confirms pre-built packs "all run on Node.js" — general docs suggest multiple languages are supporte… (WebSearch dispatched but verification did not converge within the turn budget))
  • L57 in content/docs/insights/policy/policy-groups.md "To roll out a new policy pack safely, you should add it to a purpose-built audit policy group first, review the findings, then move it to `default-policy-group…" → 🤝 matches (evidence: The claim is self-consistent with the rest of the same doc: audit groups are described as "the safest place to measure a new policy's impact before you enforce it anywhere" (audit-policy-groups section), and the preceding warning notes "Th…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L59 in content/docs/insights/policy/policy-groups.md "Pulumi's pre-built policy packs all run on Node.js, so enabling one for every stack means every developer machine and CI runner needs Node.js installed, regard…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L61 in content/docs/insights/policy/policy-groups.md "### Managing the default policy groups programmatically" → ✅ verified (evidence: The pulumi policy group CLI command exists to manage policy groups, and Pulumi docs confirm default policy groups (default-preventative-policy-group, default-audit-policy-group) are created automatically: "When you enable Pulumi Policies…; source: https://www.pulumi.com/docs/iac/cli/commands/pulumi_policy_group/)
  • L63 in content/docs/insights/policy/policy-groups.md "The default policy groups are fixed in identity and mutable only in membership; you can change what is in them but cannot change what they are, regardless of w…" → ✅ verified (evidence: Line 63 of the same doc states verbatim: "The default groups are fixed in identity and mutable only in membership. You can change what is in them; you cannot change what they are. These limits apply no matter how you make the change, inclu…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L65-72 in content/docs/insights/policy/policy-groups.md "Neither the REST API nor the pulumiservice provider supports changing a policy group's type (for example, from audit to preventative); the REST API's update…" → ✅ verified (evidence: The same doc's table at line 71 states: "Change the group's type, for example from audit to preventative | No: an update request has no field for…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L65-72 in content/docs/insights/policy/policy-groups.md "The Pulumi Cloud provider supports adding or removing cloud accounts from a policy group via the PolicyGroupInsightsAccountAttachment resource." → ✅ verified (evidence: pulumi-pulumiservice CHANGELOG.md: "Added PolicyGroupStackAttachment and PolicyGroupInsightsAccountAttachment resources for managing a single stack or Insights-account membership of a Policy Group as a standalone resource" — confirms t…; source: gh search code --owner pulumi PolicyGroupInsightsAccountAttachment (pulumi/pulumi-pulumiservice))
  • L71-72 in content/docs/insights/policy/policy-groups.md "| Change the group's type, for example from audit to preventative | No: [an update request](/docs/reference/cloud-rest-api/policy-groups/#patch-apiorgsorgnamep…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L74 in content/docs/insights/policy/policy-groups.md "The stacks, policyPacks, and insightsAccounts fields on the REST API's PATCH request replace the group's entire list, so the add* and remove* field…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L76 in content/docs/insights/policy/policy-groups.md "The pulumiservice provider cannot rename a default group or change its type because both properties force a replacement on the PolicyGroup resource, and repl…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L76 in content/docs/insights/policy/policy-groups.md "The Pulumi Cloud provider cannot rename a default group or change its type: both properties force a replacement on the PolicyGroup resource." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L76 in content/docs/insights/policy/policy-groups.md "With Pulumi IaC, each attachment resource manages a single membership, allowing users to declare one against a default group without taking ownership of the gr…" → ✅ verified (evidence: pulumi-pulumiservice CHANGELOG.md: "Added PolicyGroupStackAttachment and PolicyGroupInsightsAccountAttachment resources for managing a single stack or Insights-account membership of a Policy Group as a standalone resource, rather than…; source: gh search code --owner pulumi "PolicyGroupStackAttachment" (pulumi/pulumi-pulumiservice CHANGELOG.md and examples/api/policy-group-stack-attachment/yaml/Main.yaml))
  • L76 in content/docs/insights/policy/policy-groups.md "Policy pack membership on a default group has to be managed from the console, the CLI, or the REST API." → 🤝 matches (evidence: The same page's table (lines 65-72) shows the Pulumi Cloud provider (IaC) has "No" support for adding/removing policy packs, while the REST API supports it via addPolicyPack/removePolicyPack, and line 49 documents pulumi policy enable/`d…; source: repo:content/docs/insights/policy/policy-groups.md (lines 49, 65-72))
  • L78 in content/docs/insights/policy/policy-groups.md "Because default-policy-group cannot be deleted, renamed, or converted to an audit group, what you change to stop it from blocking deployments is its policy packs: remove them, disable them with pulumi policy disable, or set their policies to advisory." → ✅ verified (evidence: matches the page's own documented levers — L49 confirms pulumi policy disable acts on the default group when --policy-group is omitted, and the Enforcement levels section confirms enforcement is set per policy, so setting a policy to advisory stops it from blocking without removing the pack; resolved in b53aa3b; source: repo:content/docs/insights/policy/policy-groups.md)
  • L80-82 in content/docs/insights/policy/policy-groups.md "Do not manage a default policy group with the PolicyGroup resource… pulumi destroy attempts to delete it, and its policyPacks property replaces the group's entire list of policy packs." → 🤷 unverifiable (evidence: The guidance is consistent with how a full-lifecycle resource behaves and with the attachment-resource design (both confirmed elsewhere in the trail), but the specific pulumi destroy / policyPacks-replacement behavior wasn't independently confirmed. Reasonable to keep as written.)
  • L93 in content/docs/insights/policy/policy-groups.md "Policy packs in a policy group can reference Pulumi ESC environments, which lets you define configuration once and share it across every group that needs it, i…" → ✅ verified (evidence: The sibling ESC docs page confirms this exact mechanism: "The policyConfig reserved property contains values that should be exported as configuration for Pulumi policy packs. When an ESC environment is attached to a policy pack in a poli…; source: repo:content/docs/esc/concepts/outputs.md)
  • L95 in content/docs/insights/policy/policy-groups.md "When you attach an ESC environment to a policy pack, values from the environment's policyConfig and environmentVariables outputs are available to the polic…" → ✅ verified (evidence: content/docs/esc/concepts/outputs.md states: "When an ESC environment is attached to a policy pack in a policy group, environmentVariables are injected into the policy runtime as environment variables" and "The policyConfig reserved pr…; source: repo:content/docs/esc/concepts/outputs.md)
  • L97 in content/docs/insights/policy/policy-groups.md "An ESC environment reference can be pinned to a specific revision or tag, such as my-env@stable or my-env@v1, to control when the change takes effect." → ✅ verified (evidence: The ESC versioning docs confirm: "you can pin it to a specific version using a tag or revision number... append @<revision> to the environment name" and "append @tag... This ensures you are using a known, fixed version that is not affe…; source: repo:content/docs/esc/concepts/versioning.md)
  • L103 in content/docs/insights/policy/policy-groups.md "With preventative policy groups, the developer sees the violation in the pulumi preview or pulumi up command they were already running, rather than in a re…" → ✅ verified (evidence: The doc states preventative groups "act as guardrails during pulumi preview and pulumi up, evaluating the resources your program declares and reporting violations in the same command the developer was already running," while audit grou…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L103 in content/docs/insights/policy/policy-groups.md "Catching a policy problem before the resource is provisioned is the cheapest possible outcome, because nothing is created, nothing has to be remediated, and no…" → ➖ not-a-claim (evidence: This is a subjective positioning/rationale statement (an argument for why pre-provisioning policy checks are preferable) rather than a falsifiable factual claim about a specific product capability, version, or number.; source: content/docs/insights/policy/policy-groups.md (author's own framing))
  • L107 in content/docs/insights/policy/policy-groups.md "Preventative policies only see resources that Pulumi manages, so an audit group is the only way to evaluate resources changed by hand in the cloud console or b…" → 🤝 matches (evidence: The same doc states preventative groups "see only the resources Pulumi manages" (L23) and audit groups "scan on a schedule and cover every resource in the account, including resources created by hand, by another tool, or by a cloud service…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L109 in content/docs/insights/policy/policy-groups.md "An audit group gives you a full catalog of what is already non-compliant before you decide what to enforce." → ✅ verified (evidence: Same document states audit groups "continuously monitor compliance... cover every resource in the account... Audit groups report violations rather than blocking them, which makes them the safest place to measure a new policy's impact befor…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L121 in content/docs/insights/policy/policy-groups.md "Enforcement levels are set per policy pack, and per policy within a pack." → ✅ verified (evidence: pulumi/pulumi-policy CHANGELOG: "Added a top-level optional enforcementLevel on PolicyPackArgs and made enforcementLevel on Policy optional. This allows setting the enforcement level at the Policy Pack level which will apply to all…; source: gh search code --owner pulumi pulumi-policy CHANGELOG.md)
  • L127 in content/docs/insights/policy/policy-groups.md "Adding packs to an audit policy group results in nothing being blocked, and after the first scan you have a complete inventory of what would be flagged." → ✅ verified (evidence: Line 127 of the same doc reads verbatim: "Start with an audit policy group. Add the packs you are considering to an audit group covering your cloud accounts and stacks. Nothing is blocked, and after the first scan you have a complete inven…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L127-131 in content/docs/insights/policy/policy-groups.md "A recommended policy rollout process has three stages: start with an audit policy group, move to a preventative policy group with everything advisory, then mak…" → ✅ verified (framing: strengthened — the claim combines two separately-documented progressions (audit→preventative, and advisory→mandatory) into one three-stage narrative; each indi…; evidence: The official Policy Groups page confirms the audit-then-preventative rollout pattern: "Start with audit, promote to preventative: Test new policies in audit mode first to understand their impact, then promote successful p…; source: https://www.pulumi.com/docs/insights/policy/policy-groups/)
  • L129 in content/docs/insights/policy/policy-groups.md "Moving to a preventative policy group with every policy set to advisory means developers begin seeing violations at deployment time without anyone being stoppe…" → ✅ verified (evidence: Line 129 states: "Move to a preventative policy group with everything advisory... Developers begin seeing violations at deployment time... without anyone being stopped," consistent with the Advisory enforcement level definition on line 88:…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L137 in content/docs/insights/policy/policy-groups.md "The 'Check policy pack runtime requirements' page is located at /docs/insights/policy/policy-packs/#runtime-requirements." → ✅ verified (evidence: content/docs/insights/policy/policy-packs/_index.md contains a "## Runtime requirements" heading (line 49), which renders at /docs/insights/policy/policy-packs/#runtime-requirements — matching the link on line 137 of policy-groups.md exact…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L5 in content/docs/insights/policy/policy-packs/_index.md "Policy packs require a runtime on the machines that run Pulumi." → ✅ verified (evidence: The same page's "Runtime requirements" section states: "Policy packs run on the machine that runs Pulumi, so the pack's runtime must be installed there," and details per-runtime requirements (Node.js, Python, or none for OPA) — directly su…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L21 in content/docs/insights/policy/policy-packs/_index.md "Each policy pack is a project directory holding a PulumiPolicy.yaml file and one or more policies." → ✅ verified (evidence: The same doc page states "Every pack has a PulumiPolicy.yaml project file, the policy equivalent of Pulumi.yaml" and describes packs as project directories with one or more policies inside them, consistent with the claim; this matches Pulu…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L21 in content/docs/insights/policy/policy-packs/_index.md "Each policy in a policy pack inspects resources and reports a violation when something does not meet the defined standards." → ✅ verified (evidence: The doc itself states: "each policy inspects resources and reports a violation when something does not meet your standards" (line 21), which the claim faithfully paraphrases.; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L21 in content/docs/insights/policy/policy-packs/_index.md "A policy pack is the unit that Pulumi Policies publishes, versions, and applies." → ✅ verified (evidence: Pulumi's own docs describe policy packs exactly this way: "Policy packs are versioned collections of related policies that you publish and manage together," and "Policy groups apply policy packs to specific stacks or cloud accounts," confi…; source: https://www.pulumi.com/docs/insights/policy/)
  • L23 in content/docs/insights/policy/policy-packs/_index.md "A policy group determines whether policy violations block a deployment or are reported for later." → ✅ verified (evidence: The linked policy-groups page states policy groups determine enforcement pattern: preventative groups can "stop a non-compliant change before it reaches your cloud provider" while "Audit groups report violations rather than blocking them,"…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L27 in content/docs/insights/policy/policy-packs/_index.md "Pre-built policy packs cover security, cost, and operational best practices for AWS, Azure, and Google Cloud." → ✅ verified (evidence: The same source file states pre-built policy packs "cover common compliance frameworks... as well as security, cost, and operational best practices for AWS, Azure, and Google Cloud," directly matching the claim's framing.; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L29 in content/docs/insights/policy/policy-packs/_index.md "A custom policy pack can be tested locally with pulumi preview --policy-pack before publishing it to Pulumi Cloud." → ✅ verified (evidence: Sibling docs confirm this pattern: content/docs/insights/policy/cli.md states "You can run policy packs locally during pulumi preview or pulumi up by using the --policy-pack flag. This does not require Pulumi Cloud" and the tutorial…; source: repo:content/docs/insights/policy/cli.md and repo:content/tutorials/custom-policy-pack/publish-and-enforce-policy-pack/index.md)
  • L29 in content/docs/insights/policy/policy-packs/_index.md "Custom policy packs can be written in TypeScript, Python, or OPA (Rego)." → ✅ verified (evidence: The same page's runtime requirements table lists exactly three supported pack runtimes: nodejs (TypeScript/JS), python, and opa, matching the claim that custom policy packs can be written in TypeScript, Python, or OPA (Rego); the lin…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L31 in content/docs/insights/policy/policy-packs/_index.md "A policy group can hold a pre-built pack and a custom pack at the same time." → 🤝 matches (evidence: The sibling policy-groups doc states "Policy groups organize one or more policy packs and apply them to specific stacks or cloud accounts," with no restriction on mixing pre-built and custom packs; the policy-packs doc's claim that "A poli…; source: repo:content/docs/insights/policy/policy-groups.md)
  • L35 in content/docs/insights/policy/policy-packs/_index.md "The PulumiPolicy.yaml file declares the pack's runtime and, optionally, its version, description, and entry point." → ✅ verified (evidence: The project-file reference page (linked via source_hint) lists runtime as required and version, description, main (entry point) all as optional, e.g.: "runtime | required | Must be nodejs...", "version | optional | The versio…; source: repo:content/docs/insights/policy/policy-packs/project-file.md)
  • L37 in content/docs/insights/policy/policy-packs/_index.md "Policies carry metadata that Pulumi surfaces alongside findings, including a severity, remediation steps, links to external documentation, and references to th…" → ✅ verified (evidence: Line 37 of content/docs/insights/policy/policy-packs/_index.md itself states: "Policies also carry metadata that Pulumi surfaces alongside findings: a severity, remediation steps, links to external documentation, and references to the comp…; source: repo:content/docs/insights/policy/policy-packs/_index.md#L37)
  • L37 in content/docs/insights/policy/policy-packs/_index.md "A policy can examine a single resource as it is declared, or the whole stack at once when a rule depends on more than one resource." → ✅ verified (evidence: pulumi-policy SDK defines both ResourceValidationPolicy (examines a single resource) and StackValidationPolicy; CHANGELOG.md states "A new StackValidationPolicy policy type is available for defining policies that check all resources," co…; source: gh search code repo:pulumi/pulumi-policy StackValidation (CHANGELOG.md, sdk/nodejs/policy/policy.ts))
  • L39 in content/docs/insights/policy/policy-packs/_index.md "Enforcement is set per policy, and a policy can warn (advisory), block the deployment (mandatory), fix the violation automatically (remediate), or be turned of…" → ✅ verified (evidence: Pulumi's apitype/policy.go defines exactly these four EnforcementLevel values: Advisory ("the resource is still created, but a message is displayed... for informational/warning purposes"), Mandatory ("prevents a resource from being cre…; source: gh api repos/pulumi/pulumi/contents/sdk/go/common/apitype/policy.go)
  • L39 in content/docs/insights/policy/policy-packs/_index.md "A policy group can override the enforcement levels for the packs it applies, so the same pack can warn in one group and block in another." → ✅ verified (evidence: The sibling page content/docs/insights/policy/policy-groups.md states: "## Enforcement levels — Policies within policy groups can have different enforcement levels: Advisory: Issues warnings but allows deployments to proceed... **Manda…; source: gh api repos/pulumi/docs/contents/content/docs/insights/policy/policy-groups.md)
  • L41 in content/docs/insights/policy/policy-packs/_index.md "A configuration schema lets one policy pack enforce a stricter threshold in production than in development without maintaining two copies of the pack." → ✅ verified (evidence: The doc itself states at line 41: "A policy can also define a configuration schema, which turns fixed values into parameters that are set when the pack is applied. That is what lets one pack enforce a stricter threshold in production than…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L41 in content/docs/insights/policy/policy-packs/_index.md "A policy can define a configuration schema that turns fixed values into parameters set when the pack is applied." → ✅ verified (evidence: The pulumi-policy SDK includes tests confirming policy config schema support: "sets policy config schema correctly" (pb.spec.ts) and "Test GetAnalyzerInfo includes policy config schema" (test_policy.py), confirming policies can define a co…; source: gh search code --owner pulumi "policy config schema" --repo pulumi/pulumi-policy)
  • L45 in content/docs/insights/policy/policy-packs/_index.md "Publishing a pack with pulumi policy publish creates a new version rather than replacing the existing one." → 🤷 unverifiable (evidence: The cited semver.org page defines general semantic versioning rules (MAJOR.MINOR.PATCH increments and immutability of released versions) but says nothing about Pulumi's pulumi policy publish command or its behavior of creating a new vers…; source: https://semver.org/)
  • L47 in content/docs/insights/policy/policy-packs/_index.md "A policy group references a particular version of a policy pack, so publishing a new version does not change what is enforced until a group is pointed at the n…" → ✅ verified (evidence: The source doc states verbatim: "A policy group references a particular version, so publishing does not change what is enforced until a group is pointed at the new version. If you would rather track releases automatically, enable latest…; source: repo:content/docs/insights/policy/policy-packs/_index.md (L47))
  • L51 in content/docs/insights/policy/policy-packs/_index.md "A Python or Go stack governed by a TypeScript policy pack still needs Node.js installed." → 🤝 matches (evidence: The same page states: "The runtime declared in the pack's PulumiPolicy.yaml determines what is required, not the language your Pulumi program is written in. A Python or Go stack governed by a TypeScript policy pack still needs Node.js." Th…; source: repo:content/docs/insights/policy/policy-packs/_index.md)
  • L51 in content/docs/insights/policy/policy-packs/_index.md "The runtime declared in a pack's PulumiPolicy.yaml determines what runtime is required, not the language the Pulumi program is written in." → 🤝 matches (evidence: The policy-packs index page itself states: "The runtime declared in the pack's PulumiPolicy.yaml determines what is required, not the language your Pulumi program is written in. A Python or Go stack governed by a TypeScript policy pack…; source: repo:content/docs/insights/policy/policy-packs/project-file.md and repo:content/docs/insights/policy/policy-packs/_index.md)
  • L53-57 in content/docs/insights/policy/policy-packs/_index.md "A policy pack with python runtime requires Python on the machine running Pulumi, and Pulumi creates the virtual environment and installs dependencies automat…" → ✅ verified (evidence: pulumi/pulumi source shows policy_new.go defaults a virtualenv runtime option (e.g. proj.Runtime.SetOption("virtualenv", "venv")) and policypack.go comment states "If the policy's options provide a virtualenv use it, else default to "…; source: gh search code --owner pulumi "virtualenv" repo:pulumi/pulumi policy (pkg/cmd/pulumi/policy/policy_new.go, pkg/backend/httpstate/policypack.go))
  • L53-57 in content/docs/insights/policy/policy-packs/_index.md "A policy pack with runtime opa requires no separate runtime installation, because Pulumi CLI v3.227.0 and later install the OPA analyzer plugin on first use." → ✅ verified (evidence: Pulumi CLI v3.227.0 release notes list under Features: "[cli/policy] Auto-install missing policy analyzer plugins" (PR #22196), confirming automatic installation of policy analyzer plugins like the OPA analyzer starting in that version.; source: gh release view v3.227.0 -R pulumi/pulumi)
  • L59 in content/docs/insights/policy/policy-packs/_index.md "If any of the pre-built policy packs (CIS, PCI DSS, NIST, HITRUST, ISO 27001, CMMC, or Pulumi Best Practices) is enabled, every machine that runs pulumi previ…" → ✅ verified (evidence: Source file states verbatim: "Pulumi's pre-built policy packs all run on Node.js. If you enable CIS, PCI DSS, NIST, HITRUST, ISO 27001, CMMC, or Pulumi Best Practices, every machine that runs pulumi previeworpulumi up` against a gover…; source: repo:content/docs/insights/policy/policy-packs/_index.md (line 59))
  • L61 in content/docs/insights/policy/policy-packs/_index.md "A policy pack that declares runtime: nodejs is always executed with Node.js, even when the stack's own program uses Bun." → ✅ verified (evidence: The linked source confirms "As of Pulumi 3.227.0 Bun is also supported as a first-class runtime. To use Bun, set runtime: bun in your Pulumi.yaml" for Pulumi programs, while the policy-packs page independently states policy pack runtim…; source: repo:content/docs/iac/languages-sdks/javascript/_index.md and repo:content/docs/insights/policy/policy-packs/_index.md)
  • L63 in content/docs/insights/policy/policy-packs/_index.md "When Pulumi Cloud enforces a policy pack through a policy group, the CLI downloads the pack to ~/.pulumi/policies and installs its dependencies the first tim…" → ✅ verified (evidence: Sibling docs corroborate both halves of the claim: content/docs/insights/policy/cli.md states "policy packs enabled through policy groups are downloaded and applied automatically," and content/docs/insights/policy/ci-cd.md / dependency-cac…; source: gh search code --owner pulumi ".pulumi/policies" (content/docs/insights/policy/ci-cd.md, content/docs/deployments/concepts/settings/dependency-caching.md, content/docs/insights/policy/cli.md))
  • L69 in content/docs/insights/policy/policy-packs/_index.md "Policies can be run in CI/CD, as documented at /docs/insights/policy/ci-cd/." → ✅ verified (evidence: The page content/docs/insights/policy/ci-cd.md exists in pulumi/docs and Hugo renders it at the URL /docs/insights/policy/ci-cd/, matching the linked path in the claim.; source: gh api repos/pulumi/docs/contents/content/docs/insights/policy (shows ci-cd.md present))
  • L48 in content/docs/insights/policy/policy-packs/authoring.md "The Pulumi Policy as Code documentation page at /docs/insights/policy/policy-packs/ contains a section titled 'runtime requirements' (anchored at #runtime-requ…" → ✅ verified (evidence: The sibling page content/docs/insights/policy/policy-packs/_index.md (rendered at /docs/insights/policy/policy-packs/) contains the heading '## Runtime requirements' at line 49, which generates the anchor #runtime-requirements, matching th…; source: repo:content/docs/insights/policy/policy-packs/_index.md)

🚨 Outstanding in this PR

No outstanding findings in this PR.

⚠️ Low-confidence

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

  • [L54] content/docs/insights/policy/policy-groups.md"Pulumi's pre-built policy packs all run on Node.js." — verdict: 🤷 unverifiable. The public pre-built packs page lists the frameworks the packs cover but doesn't state the runtime they're implemented in, so this couldn't be confirmed externally. It's the load-bearing fact behind the PR's repeated "everyone needs Node.js" guidance (it also appears at L59 and L126 of the diff, and in ci-cd.md), so if it's wrong the guidance across several pages is wrong. @jkodroff — can you confirm that every pre-built pack (CIS, PCI DSS, NIST, HITRUST, ISO 27001, CMMC, Pulumi Best Practices) ships as a nodejs pack? This is not a merge blocker, but it's the one fact worth double-checking before merge.

  • [L59] content/docs/insights/policy/policy-groups.md"Pulumi's pre-built policy packs all run on Node.js, so enabling one for every stack means every developer machine and CI runner needs Node.js installed, regardless of language." — verdict: 🤷 unverifiable. Same underlying fact as L54 — the conclusion holds only if every pre-built pack is a nodejs pack. Confirming L54 confirms this one; no separate action needed.

  • [L71-72] content/docs/insights/policy/policy-groups.md"Change the group's type, for example from audit to preventative | No: an update request has no field for it" — verdict: 🤷 unverifiable. The verification step couldn't confirm from the REST API reference that the PATCH body has no type field. @jkodroff — please confirm the REST API exposes no way to change a group's type, since the table asserts a hard "No".

  • [L74] content/docs/insights/policy/policy-groups.md"The stacks, policyPacks, and insightsAccounts fields on the REST API's PATCH request replace the group's entire list, so use the add* and remove* fields to change one membership at a time." — verdict: 🤷 unverifiable. Couldn't confirm the replace-vs-merge semantics of those PATCH fields from the reference. @jkodroff — please confirm the bare list fields replace the whole list while add*/remove* are incremental, since a reader following this could otherwise wipe a group's membership.

  • [L76] content/docs/insights/policy/policy-groups.md"…both properties force a replacement on the PolicyGroup resource, and replacing a group means deleting it first, which Pulumi Cloud rejects for a default group." — verdict: 🤷 unverifiable. The replacement-triggering behavior of the name/type properties couldn't be confirmed against the provider schema. See the companion note on the next bullet — one confirmation covers both.

  • [L76] content/docs/insights/policy/policy-groups.md"The provider also cannot rename a default group or change its type: both properties force a replacement on the PolicyGroup resource." — verdict: 🤷 unverifiable. @jkodroff — please confirm the name and type properties on the pulumiservice PolicyGroup resource are replace-triggering (create-before-delete forcing a delete Pulumi Cloud rejects for defaults). This underpins both L76 statements.

  • [L80-82] content/docs/insights/policy/policy-groups.md"Do not manage a default policy group with the PolicyGroup resource… pulumi destroy attempts to delete it, and its policyPacks property replaces the group's entire list of policy packs." — verdict: 🤷 unverifiable. The guidance is consistent with how a full-lifecycle resource behaves and with the attachment-resource design (both confirmed elsewhere in the trail), but the specific pulumi destroy / policyPacks-replacement behavior wasn't independently confirmed. Reasonable to keep as written, flagging only so the author can sanity-check the policyPacks-replaces-the-list detail.

Vale (style linting) wasn't runnable in this environment for this pass, so no fresh [style] findings are rendered here. Style nits aren't tracked across reviews, so the three from the previous run (weasel words / wordiness) aren't carried forward — they'll resurface on the next run where Vale is available if still present.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

📋 Triaged verifier findings

I double-checked these and realized they weren't real findings — click to expand
  • [L45] content/docs/insights/policy/policy-packs/_index.md"Publishing a pack with pulumi policy publish creates a new version rather than replacing the existing one." — verdict was 🤷 unverifiable. Mis-sourced: the verification step checked this against the semver.org link that sits next to the sentence, which only defines the versioning scheme and says nothing about pulumi policy publish. The publish-creates-a-new-immutable-version behavior is standard, documented Pulumi behavior; no author action needed.

💡 Pre-existing issues in touched files (optional)

No pre-existing issues in touched files.

✅ Resolved since last review

  • [L78] content/docs/insights/policy/policy-groups.md — the "removing its policy packs is the only way to stop it from enforcing anything" overclaim. Reworded to name the actual levers — remove the pack, disable it with pulumi policy disable, or set its policies to advisory — none of which require deleting, renaming, or converting the group. (resolved in b53aa3b)

📜 Review history

  • 2026-07-29T16:51:45Z — One overclaim flagged ("only way to stop enforcing" — disabling/advisory also work); several REST-API/provider behavior claims and the "pre-built packs all run on Node.js" fact left for author confirmation; cross-sibling rename check clean. (456d69f)
  • 2026-07-29T18:59:40Z — Re-reviewed after fix push (1 new commit): the "only way to stop enforcing" overclaim is fixed as suggested and moved to ✅ Resolved; swept the rest of the touched pages for the same phrase, none found. Outstanding is now empty. Remaining low-confidence items (REST API/provider replace-vs-merge and replacement-trigger behavior, pre-built-packs-Node.js runtime) are unchanged and still need author confirmation. (b53aa3b)

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 Jul 29, 2026
Removing packs isn't the only lever: `pulumi policy disable` acts on the
default group, and enforcement is set per policy, so advisory works too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added review:stale New commits since last Claude review; refresh on next ready-transition or @claude mention and removed review:outstanding-issues Claude review completed; outstanding has author-actionable findings labels Jul 29, 2026
@jkodroff

Copy link
Copy Markdown
Member Author

@claude #update-review

@github-actions github-actions Bot added review:in-progress Claude review is currently running and removed review:stale New commits since last Claude review; refresh on next ready-transition or @claude mention labels Jul 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Review updated on @jkodroff's request.

@github-actions github-actions Bot added review:no-blockers Claude review completed cleanly; outstanding is empty and removed review:in-progress Claude review is currently running labels Jul 29, 2026

@CamSoper CamSoper left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with one question

## Types of policy packs

Pulumi offers two approaches to policy enforcement:
- <a id="pre-built-policy-packs"></a>**[Pre-built policy packs](/docs/insights/policy/policy-packs/pre-built-packs/)** are written and maintained by Pulumi. They cover common compliance frameworks, including CIS, PCI DSS, HITRUST, and NIST, as well as security, cost, and operational best practices for AWS, Azure, and Google Cloud. You enable them from Pulumi Cloud without writing any code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the anchors? I don't see any links to these anywhere.

@jkodroff
jkodroff merged commit ab88f20 into master Jul 29, 2026
16 checks passed
@jkodroff
jkodroff deleted the jkodroff/default-policy-groups branch July 29, 2026 21:49
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:no-blockers Claude review completed cleanly; outstanding is empty

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document the default policy groups

3 participants