Skip to content

Document access token expiry policy and add announcement post#20344

Open
djgrove wants to merge 13 commits into
masterfrom
dg/access-token-expiry-policy
Open

Document access token expiry policy and add announcement post#20344
djgrove wants to merge 13 commits into
masterfrom
dg/access-token-expiry-policy

Conversation

@djgrove

@djgrove djgrove commented Jul 17, 2026

Copy link
Copy Markdown
Member

Proposed changes

Documents the new organization-level access token expiry policy, which lets org admins cap the maximum expiry (in days) of personal, organization, and team tokens used against their organization.

The new docs section covers setup, the remaining-lifetime compliance rule (checked on every request, so never-expiring tokens always violate and old long-expiry tokens age into compliance), per-token-type enforcement, and exemptions. All behavior claims were verified against the backend implementation. A pre-existing stale nav path elsewhere on the page is also fixed.

The announcement post links to that section and focuses on rolling the policy out without breaking CI, built around the Preview affected tokens flow. Feature image rendered with the lock + clock-countdown template.

djgrove and others added 2 commits July 17, 2026 09:22
Adds an "Access token expiry policy" section to the access tokens docs
covering setup, remaining-lifetime compliance semantics, per-token-type
enforcement, and exemptions, plus a product blog post announcing the
feature that links to the new docs section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yk8AACv3fac6fSQkTtudT
- Replace meta_image screenshot override with a rendered feature image
  (lock + clock-countdown template) per the blog archetype convention
- Drop canonical_url: current feature announcements let the post rank
  and link to docs in-body instead
- Extend the docs exemption list with internally issued credentials
  (deployment agent pool tokens)
- Fix the pre-existing stale nav path for organization tokens
- Add 1px border to the settings screenshot

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yk8AACv3fac6fSQkTtudT
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Social Media Review

content/blog/access-token-expiry-policy/index.md

X — PASS

LinkedIn — PASS

Bluesky — PASS


Suggestions (advisory)

These are stylistic notes — they don't block the post.

X

  • No pointer to the article — the copy fully describes the feature and its mechanism, with nothing signaling there's more to read
  • Curiosity gap closed — "Set the cap once; the platform enforces it on every request" leaves the article's mechanism with nothing new to reveal

LinkedIn

  • Closing line promises "how it works," but paragraphs 2-3 already deliver the mechanism (cap set in days, checked on every request, rejection behavior and error message) — the article is left to cover only rollout

Bluesky

  • Curiosity gap closed — the post already gives the full mechanism, leaving nothing new for the article to reveal
  • Missing pointer — ends on the mechanism description with no line inviting the reader into the article for more

Updated for commit c2d68fa4e7997607490ea7753b8b11430edb97f6 (short: c2d68fa) at 2026-07-17 17:54 UTC.

@djgrove
djgrove marked this pull request as ready for review July 17, 2026 17:21
@github-actions github-actions Bot added review:triaging Claude Triage is currently classifying the PR domain:docs PR touches technical docs domain:mixed PR touches more than one domain domain:blog PR touches blog posts or customer stories review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels Jul 17, 2026
@pulumi-bot

pulumi-bot commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Pre-merge Review — Last updated 2026-07-25T01:24:25Z

Tip

Summary: This PR adds a product-announcement blog post for the new Pulumi Cloud access token expiry policy and a matching Access token expiry policy reference section in the access-tokens docs page. A reader would be blocked by a wrong settings path, incorrect setup steps, or inaccurate claims about how enforcement and compliance work, so verification concentrated on the configuration steps, the compliance rule, and the cross-links to the docs, audit-logs, and OIDC pages. Since the last review, 7 new commits reworked the post's UI walkthrough: they replaced the original screenshot with 8 new screenshots depicting a consistent 14-day/acme-corp scenario, added a concrete CLI 403-rejection example, fixed a preview-truncation overclaim ("every ... by name" → "the first five, plus a count"), and scoped the lede from "all tokens" to the three token types the policy actually checks. That last fix corrected the post's own body text but missed two duplicate occurrences of the old, overbroad phrasing in the Twitter and Bluesky social captions — both still claim the policy covers "every access token," which the post's own body contradicts (OIDC-exchanged tokens are explicitly exempt). New unverifiable implementation details (a 5-item preview-list cap, the exact CLI error text, the new screenshots' specific numbers) get the same "can't independently confirm, ask the author" treatment as the items already in Low-confidence. The two pre-existing factual contradictions from the initial review remain, unchanged and still out of scope for this PR.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts MEDIUM New contradiction found in social copy (scoped correctly in the body, not in twitter/bluesky). Several new implementation-detail claims (preview truncation limit, exact CLI error text, new screenshot contents) are internally consistent but unverifiable, same as before. Two pre-existing contradictions remain in sections this PR doesn't touch.
coherence HIGH
Investigation log
  • Cross-sibling reads: not run (not in a templated section)
  • External claim verification: 80 of 95 claims verified (7 unverifiable, 4 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 77 Pass 1, 1 Pass 2 (verified 0, contradicted 1, unverifiable 0), 17 Pass 3 (verified 10, contradicted 0, unverifiable 7).
  • Cited-claim spot-checks: 1 of 1 cited claims fetched and compared
  • Frontmatter sweep: ran on body + meta_desc + social.{bluesky, linkedin, twitter}
  • 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; the new error: example block is CLI output, not sample code)
  • Editorial-balance pass: ran (single-subject, N/A)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
1 6 2 1

🔍 Verification trail

96 claims extracted · 80 verified · 7 unverifiable · 4 contradicted
  • L15 in content/blog/access-token-expiry-policy/index.md "Pulumi Cloud organizations can now enforce a maximum expiry on every access token used against them." (also L29) → ❌ contradicted (narrowed — claim broadens "personal, organization, and team tokens" to "every access token"; the post's own body states short-lived tokens issued through OIDC token exchange are exempt and "already bounded by their issuer"; evidence: content/blog/access-token-expiry-policy/index.md L65 "as are the short-lived tokens issued through OIDC token exchange... those are already bounded by their issuer"; source: repo:content/blog/access-token-expiry-policy/index.md)
  • L127 in content/docs/administration/access-identity/access-tokens.md "Preview affected tokens lists the organization and team tokens that would fail to authenticate under the proposed cap, by name and creator (the first five, plus a count of any others)." → 🤷 unverifiable (evidence: new, unreleased UI behavior with no external source to confirm the five-item truncation limit; internally consistent with the fix commit's own rationale ("The preview names at most five affected tokens plus a count"); source: content/docs/administration/access-identity/access-tokens.md (L127))
  • L48 in content/blog/access-token-expiry-policy/index.md "The access token expiry policy card in Pulumi Cloud organization settings, with a 14-day maximum entered and buttons to preview affected tokens and save the policy." (also L52, L69, L77, L81) → 🤷 unverifiable (evidence: five new screenshots depicting a 14-day cap / acme-corp org scenario across the settings card, banner, capped creation dialog, affected-tokens preview, and CLI rejection; contents can't be independently rendered or confirmed, though the alt text is internally consistent across all five images and with the surrounding prose; source: content/blog/access-token-expiry-policy/index.md)
  • L125 in content/docs/administration/access-identity/access-tokens.md "The Other tab of the Access Management settings page, with the access token expiry policy section at the bottom." (also L129, L144, L148, L150) → 🤷 unverifiable (evidence: five screenshots (two shared with the blog) depicting the Other-tab settings location, the affected-tokens preview, the capped creation dialog, and the two personal-token policy-warning surfaces; contents can't be independently rendered or confirmed, though alt text is internally consistent with the surrounding prose; source: content/docs/administration/access-identity/access-tokens.md)
  • L157 in content/docs/administration/access-identity/access-tokens.md "error: could not create stack: [403] The acme-corp organization enforces a max access token expiry of 14 days that your current token does not meet. Please generate a new token with a TTL meeting your org's threshold to perform this request." (also L81 in content/blog/access-token-expiry-policy/index.md) → 🤷 unverifiable (evidence: the exact wording of the live 403 response can't be confirmed from documentation alone, same limitation as the general claim already reviewed at this location; internally consistent with the page's own description that the message "names the organization and its policy maximum"; source: content/docs/administration/access-identity/access-tokens.md (L154))
  • L146 in content/docs/administration/access-identity/access-tokens.md "the member's Personal access tokens page summarizes the strictest policies across their organizations" → 🤝 matches (evidence: the new personal-tokens-policy-warning.png screenshot's own alt text describes "a banner that one organization enforces a maximum access token expiry of 14 days" on that exact page, corroborating the claim; source: content/docs/administration/access-identity/access-tokens.md (L150))
  • L50 in content/blog/access-token-expiry-policy/index.md "You can also get there from the Access Tokens tab, where a banner shows whether a policy is in effect — select Edit policy." (also L131 in content/docs/administration/access-identity/access-tokens.md) → 🤝 matches (evidence: the docs page states the identical behavior: "While a policy is active, the Access Tokens tab shows a banner with the current cap and an Edit policy shortcut to this setting," directly corroborating the blog's claim; source: content/docs/administration/access-identity/access-tokens.md)
  • L120 in content/docs/administration/access-identity/access-tokens.md "Navigate to Settings > Access Management and select the Other tab." → 🤝 matches (evidence: "Select the Other tab" under Settings > Access Management is an established navigation pattern already used by several sibling docs pages (SAML/SCIM setup guides, organizations.md), corroborating that this is a real settings tab rather than a stale/incorrect path; source: repo:content/docs/administration/organizations-teams/organizations.md, repo:content/docs/administration/access-identity/saml/okta.md)

(Previously-verified claims from the initial review carry forward unchanged; see the 📜 Review history for the original 89-claim trail.)

📊 Editorial balance

Single-subject post; balance check N/A.

🚨 Outstanding in this PR

These must be resolved or refuted before merging.

  • [L15] content/blog/access-token-expiry-policy/index.md"Pulumi Cloud organizations can now enforce a maximum expiry on every access token used against them." (also the Bluesky caption, L29: "cap the max expiry of every access token used against their organization") — Contradicted by the post's own body (L65): short-lived tokens issued through OIDC token exchange are explicitly exempt from the policy ("already bounded by their issuer"). The body lede was already fixed in commit 0d13c44 to scope this claim down to "personal, organization, and team tokens," but the Twitter and Bluesky social captions still carry the old, overbroad "every access token" phrasing. Author: scope both captions the same way the body and the LinkedIn caption already are (the LinkedIn caption — L21 — correctly says "for personal, organization, and team tokens alike... Web console sessions are unaffected").

⚠️ Low-confidence

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

  • [L127] content/docs/administration/access-identity/access-tokens.md"Preview affected tokens lists the organization and team tokens that would fail to authenticate under the proposed cap, by name and creator (the first five, plus a count of any others)." — New unreleased-feature behavior detail; can't be confirmed from documentation alone, but matches the fix commit's stated rationale. Not a blocker. Author: confirm the preview actually truncates at five plus a count.

  • [L48] content/blog/access-token-expiry-policy/index.mdthe new screenshot set (expiry-policy-card.png, expiry-policy-banner.png, new-token-dialog-capped.png, preview-affected-tokens.png, policy-rejection-cli.png) — All five consistently depict a 14-day cap / acme-corp org scenario, replacing the single screenshot flagged in the previous review. Contents can't be independently rendered or confirmed. Not a blocker. Author: confirm the screenshots match what's actually shipped (14-day cap, acme-corp naming, one affected token).

  • [L125] content/docs/administration/access-identity/access-tokens.mdthe docs-page screenshot set (expiry-policy-other-tab.png, expiry-policy-preview.png, new-token-dialog-capped.png, personal-token-dialog-policy-warning.png, personal-tokens-policy-warning.png) — Same treatment as the blog screenshots above; internally consistent with the surrounding prose but unverifiable from documentation alone. Not a blocker. Author: confirm these match the actual shipped UI.

  • [L138] content/docs/administration/access-identity/access-tokens.md"For example, under a 30-day policy, a token that expires 20 days from now is compliant even if it was originally created with a one-year expiry." — This illustrative example describes brand-new feature behavior with no external source to confirm it against; it's internally consistent with the compliance rule stated above it. Not a blocker (unchanged from the previous review; line number shifted from L131-132 due to the new screenshots inserted above it). Author: confirm the 30-day / 20-day figures match the shipped enforcement behavior.

  • [L157] content/docs/administration/access-identity/access-tokens.md"error: could not create stack: [403] The acme-corp organization enforces a max access token expiry of 14 days that your current token does not meet..." (also the policy-rejection-cli.png screenshot at blog L81) — The previous review flagged the general claim that rejections "name the organization and its policy maximum" as unverifiable; this PR adds a concrete example that's consistent with that description, but the exact wording still can't be confirmed from documentation alone. Not a blocker. Author: confirm the CLI error text matches what the platform actually returns.

Style findings

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

Click each filename to expand.

content/blog/access-token-expiry-policy/index.md (10 issues: 10 wordiness)
  • line 5: [style] wordiness — 'maximum' is too wordy.
  • line 32: [style] wordiness — 'maximum' is too wordy.
  • line 32: [style] wordiness — 'expiration' is too wordy.
  • line 48: [style] wordiness — 'maximum' is too wordy.
  • line 54: [style] wordiness — 'maximum' is too wordy.
  • line 56: [style] wordiness — 'expiration' is too wordy.
  • line 57: [style] wordiness — 'expiration' is too wordy.
  • line 63: [style] wordiness — 'maximum' is too wordy.
  • line 64: [style] wordiness — 'all of' is too wordy.
  • line 67: [style] wordiness — 'maximum' is too wordy.
content/docs/administration/access-identity/access-tokens.md (10 issues: 9 wordiness, 1 future tense)
  • line 35: [style] wordiness — 'expiration' is too wordy.
  • line 35: [style] future tense — Future tense ('the token will no') -- prefer present tense for product behavior: 'Neo pauses', not 'Neo will pause' (STYLE-GUIDE.md §Grammar and punctuation).
  • line 35: [style] wordiness — 'expiration' is too wordy.
  • line 114: [style] wordiness — 'maximum' is too wordy.
  • line 114: [style] wordiness — 'expiration' is too wordy.
  • line 114: [style] wordiness — 'expiration' is too wordy.
  • line 121: [style] wordiness — 'maximum' is too wordy.
  • line 135: [style] wordiness — 'expiration' is too wordy.
  • line 135: [style] wordiness — 'expiration' is too wordy.
  • line 135: [style] wordiness — 'maximum' is too wordy.

💡 Pre-existing issues in touched files (optional)

Both items are on lines this PR does not modify — flagged as follow-ups, not blockers for this PR.

  • [L101] content/docs/administration/access-identity/access-tokens.md"If an organization's default stack access is set to Read, a team token can read every stack in the organization, not just the stacks the team has been granted." — Recorded as ❌ contradicted: the RBAC and teams reference pages describe the organization's default stack access as applying to organization members on the Member role, not to team tokens gaining org-wide read access beyond their team's grants. Still pre-existing content in the "Team access tokens" section; only a link-format fix (trailing slash) touched this line since the last review, not the substantive claim. Recommend a follow-up to reconcile the wording with rbac/roles.md.

  • [L176] content/docs/administration/access-identity/access-tokens.md"To perform operations that require elevated access, such as creating or deleting stacks, a user must explicitly request the admin scope when exchanging the OIDC token." — Recorded as ❌ contradicted: the OIDC Issuers reference defines the token-exchange scope parameter as targeting a team or user (team:{TEAM_NAME} / user:{USER_LOGIN}), which conflicts with this page's description of an admin scope. Pre-existing, untouched by any commit since the last review — recommend a follow-up to reconcile the two pages.

✅ Resolved since last review

  • [L48] content/blog/access-token-expiry-policy/index.md"The access token expiry policy card in Pulumi Cloud organization settings shows a 1000-day cap and a preview listing one affected machine token." — Superseded: expiry-policy-settings.png was deleted and replaced with a new, consistent 14-day/acme-corp screenshot set (resolved in f68f67e). The original 1000-day figure no longer appears anywhere in the PR.

📜 Review history

  • 2026-07-17T17:25:12Z — No blockers in the new blog + docs content; cleared a spurious GitHub-URL mismatch and routed two pre-existing docs contradictions (team-token stack read, OIDC admin scope) to follow-ups. (4463e13)
  • 2026-07-20T23:47:47Z — Re-verified after 2 follow-up commits trimming the post's social: copy (LinkedIn/Twitter shortened, Bluesky reformatted); no new claims, no outstanding findings affected, style-finding line numbers refreshed against the current head. (c2d68fa)
  • 2026-07-25T01:24:25Z — Re-reviewed after 7 fix-response commits (new screenshot set, CLI-rejection example, preview-truncation and token-scope wording fixes, rollout-step reword, publish-date bumps): resolved the superseded 1000-day screenshot finding, and raised one new 🚨 finding — the lede-scoping fix left the old, overbroad "every access token" phrasing in the Twitter and Bluesky captions. (d391677)

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:no-blockers Claude review completed cleanly; outstanding is empty and removed review:in-progress Claude review is currently running labels Jul 17, 2026
djgrove and others added 2 commits July 17, 2026 10:48
Adopts the social-review check's suggested rewrites: trims the X copy
to 228/255 chars and splits the Bluesky copy into two paragraphs as
the platform requires. No wording changes beyond the X tail trim.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yk8AACv3fac6fSQkTtudT
…s reveal

Per the social-review advisory: the LinkedIn body walked through the
full rollout flow, leaving the closing "here's how it works" pointer
with nothing to reveal. Drops the preview-before-save detail so the
linked article keeps a concrete hook.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yk8AACv3fac6fSQkTtudT
@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:no-blockers Claude review completed cleanly; outstanding is empty labels Jul 17, 2026

Copy link
Copy Markdown
Contributor

@claude #update-review


Generated by Claude Code

@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 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Review updated on @CamSoper'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 20, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yk8AACv3fac6fSQkTtudT
Blog: replace the stale 1000-day policy-card screenshot with the 14-day
walkthrough set (policy card, capped creation dialog, affected-tokens
preview). Docs: illustrate setting the policy, the preview, and both
member-facing warnings (creation dialog and personal tokens page).

Also correct the navigation path in both: the policy card lives on the
Other tab of Access Management, not the Access Tokens tab, which only
shows the policy banner with an Edit policy shortcut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197xXQsvZB6qdBSg6CmCdGs
Blog gets the terminal screenshot of pulumi up failing against the
policy; docs get the same error as a code block so the message text is
searchable. Wording matches the service's canonical message.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197xXQsvZB6qdBSg6CmCdGs
@pulumi-bot

pulumi-bot commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Lighthouse Performance Report

Commit: 73b40b4 | Metric definitions

Page Device Score FCP LCP TBT CLS SI
Homepage Mobile 🔴 28 8.0s 15.0s 1844ms 0.000 10.3s
Homepage Desktop 🟡 87 0.7s 1.8s 156ms 0.019 1.3s
Install Pulumi Mobile 🟡 56 6.2s 13.8s 127ms 0.053 7.8s
Install Pulumi Desktop 🟡 77 1.2s 2.5s 0ms 0.015 2.7s
AWS Get Started Mobile 🔴 46 5.8s 9.8s 38ms 0.234 7.9s
AWS Get Started Desktop 🟡 75 1.2s 2.8s 0ms 0.033 2.7s

The preview names at most five affected tokens plus a count, so drop
"every ... by name" phrasing in blog and docs. Scope the lede to the
three token types the policy actually checks (web sessions and
system-minted tokens are exempt). Fix a missing space and add the
trailing slash on the roles link.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197xXQsvZB6qdBSg6CmCdGs
@djgrove

djgrove commented Jul 25, 2026

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 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Review updated on @djgrove's request.

@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 25, 2026
The preview detail and its screenshot become part of the preview step,
and the Other-tab screenshot nests under the navigation step instead of
dangling after the list. Gloss the 3650-day bound as 10 years.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197xXQsvZB6qdBSg6CmCdGs
@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 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:blog PR touches blog posts or customer stories domain:docs PR touches technical docs domain:mixed PR touches more than one domain review:stale New commits since last Claude review; refresh on next ready-transition or @claude mention

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants