Skip to content

JWT tokens account as operators#1385

Merged
hcourdent merged 1 commit intomainfrom
external_jwt_pricing
May 6, 2026
Merged

JWT tokens account as operators#1385
hcourdent merged 1 commit intomainfrom
external_jwt_pricing

Conversation

@hcourdent
Copy link
Copy Markdown
Contributor

No description provided.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 6, 2026

Claude finished @hcourdent's task in 2m 52s —— View job


PR review

  • Read PR context
  • Review diff against AGENTS.md / writing_style_guide.md / REVIEW.md
  • Verify changed files for factual / link / frontmatter issues
  • Post review

Summary

The PR documents that external JWT tokens are billed as half-a-seat operators across the docs, the pricing FAQ, the seat slider, and the feature list. The factual content is consistent across the seven files. No P0/P1 issues found — links resolve (/docs/advanced/external_auth_with_jwt matches the 16_external_auth_with_jwt folder after numeric prefix stripping), the #users and #operator anchors exist in roles_and_permissions, the EE-on-first-mention rule is preserved (docs/advanced/16_external_auth_with_jwt/index.mdx already linked EE on the prior line), and no frontmatter is touched. Three P2 nits posted as inline suggestions.

Findings

Severity File:line Issue
P2 docs/misc/19_enterprise_onboarding/index.mdx:361 New em dash () introduced — AGENTS.md says to avoid them. Inline
P2 src/components/pricing/PricingFAQ.js:83 New em dash introduced. Inline
P2 docs/core_concepts/16_roles_and_permissions/index.mdx:97 Trailing clause "and each external JWT token in use also counts as half a seat (same as an operator)" restates what the preceding clause already says. Inline

Pre-existing em dashes in docs/misc/7_plans_details/index.mdx and elsewhere were left out of scope — they're not introduced by this PR.

AGENTS.md / writing_style_guide.md compliance

  • Em dash rule: 2 violations introduced (flagged above).
  • Headings: untouched, no sentence-case regressions.
  • Backlinks on first mention: present (external JWT, operator, seat all link out).
  • EE on first mention: docs/advanced/16_external_auth_with_jwt/index.mdx keeps the existing [Enterprise Edition](/pricing) link on line 10; no new pages need it.
  • FAQ textAnswer: both edited entries (pricing-explained, operator) keep their textAnswer fields and updated them to mention JWT — good.
  • Frontmatter description: no frontmatter touched, no new pages added.
  • sidebars.js: no new pages → no registration needed.
  • JSON-LD: pricing page schemas untouched and still valid (FAQPage textAnswer fields preserved).

Verification

  • npm run build should succeed: no broken internal links (#users, #operator, /docs/advanced/external_auth_with_jwt all resolve), no MDX structural changes, no new files referenced from sidebars.js.
  • For the React changes, manual verification worth doing locally:
    • Pricing page: confirm the operator slider tooltip renders the new "operator or ext JWT token" label without overflow at small widths (PriceCalculator.js:474–483).
    • Pricing FAQ: expand the "What is an operator?" entry and the seat-billing entry to confirm the inline <Link> to /docs/advanced/external_auth_with_jwt renders in both light and dark mode.
    • Feature list: confirm the longer name ("External auth with JWT (each token billed as 1/2 seat)") fits the table cell on the comparison page without wrapping awkwardly.
      · branch external_jwt_pricing

### Seats

A Seat is a user who is active on the platform. A regular user counts as one Seat, while an [operator](../../core_concepts/16_roles_and_permissions/index.mdx#operator) (who can only execute scripts, flows, and apps) counts as half a Seat. We only count active users, i.e. users who have logged in to the platform in the last 30 days according to the audit logs. Seats are counted across all instances (dev, prod) but Windmill only counts once the same user.
A Seat is a user who is active on the platform. A regular user counts as one Seat, while an [operator](../../core_concepts/16_roles_and_permissions/index.mdx#operator) (who can only execute scripts, flows, and apps) counts as half a Seat. Each [external JWT token](../../advanced/16_external_auth_with_jwt/index.mdx) used in the last 30 days is also billed as half a Seat (same as an operator) — for seat counting, you can mix operators and external JWT tokens freely (e.g. 1 operator + 1 external JWT token = 1 Seat). We only count active users, i.e. users who have logged in to the platform in the last 30 days according to the audit logs. Seats are counted across all instances (dev, prod) but Windmill only counts once the same user.
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.

P2 — em dash. AGENTS.md says: "Avoid using symbol '—' as it looks like obvious AI. Use sentences not using it or use '-' instead." This added clause is the only em dash this PR introduces in this file.

Suggested change
A Seat is a user who is active on the platform. A regular user counts as one Seat, while an [operator](../../core_concepts/16_roles_and_permissions/index.mdx#operator) (who can only execute scripts, flows, and apps) counts as half a Seat. Each [external JWT token](../../advanced/16_external_auth_with_jwt/index.mdx) used in the last 30 days is also billed as half a Seat (same as an operator) — for seat counting, you can mix operators and external JWT tokens freely (e.g. 1 operator + 1 external JWT token = 1 Seat). We only count active users, i.e. users who have logged in to the platform in the last 30 days according to the audit logs. Seats are counted across all instances (dev, prod) but Windmill only counts once the same user.
A Seat is a user who is active on the platform. A regular user counts as one Seat, while an [operator](../../core_concepts/16_roles_and_permissions/index.mdx#operator) (who can only execute scripts, flows, and apps) counts as half a Seat. Each [external JWT token](../../advanced/16_external_auth_with_jwt/index.mdx) used in the last 30 days is also billed as half a Seat (same as an operator). For seat counting, you can mix operators and external JWT tokens freely (e.g. 1 operator + 1 external JWT token = 1 Seat). We only count active users, i.e. users who have logged in to the platform in the last 30 days according to the audit logs. Seats are counted across all instances (dev, prod) but Windmill only counts once the same user.

>
external JWT token
</Link>{' '}
in use is billed the same way as an operator (1/2 seat). For seat counting, you can mix operators and external JWT tokens freely — for example, 1 operator + 1 external JWT token = 1 seat.
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.

P2 — em dash. AGENTS.md: "Avoid using symbol '—' as it looks like obvious AI. Use sentences not using it or use '-' instead." This is one of two new em dashes the PR introduces.

Suggested change
in use is billed the same way as an operator (1/2 seat). For seat counting, you can mix operators and external JWT tokens freely for example, 1 operator + 1 external JWT token = 1 seat.
in use is billed the same way as an operator (1/2 seat). For seat counting, you can mix operators and external JWT tokens freely (for example, 1 operator + 1 external JWT token = 1 seat).

- [Workers](../9_worker_groups/index.mdx)

Regarding to [Pricing](/pricing), operators are counted as half of a regular seat ([developers](#developer)) as long as they are operators in all workspaces they are members of. Operators are not set as the instance-level. On the billing side, 1 developer seat or 2 operators seats count as 1 seat, there is no need to differentiate between developers and operators when purchasing the license.
Regarding to [Pricing](/pricing), operators are counted as half of a regular seat ([developers](#developer)) as long as they are operators in all workspaces they are members of. Operators are not set as the instance-level. On the billing side, 1 developer seat or 2 operator/[external JWT token](../../advanced/16_external_auth_with_jwt/index.mdx) seats count as 1 seat, and each external JWT token in use also counts as half a seat (same as an operator). There is no need to differentiate between developers, operators and external JWT tokens when purchasing the license.
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.

P2 — redundant clause. The first half of the sentence already establishes the half-seat math via "1 developer seat or 2 operator/external JWT token seats count as 1 seat". The added trailing clause "and each external JWT token in use also counts as half a seat (same as an operator)" then restates the same fact, which makes the sentence harder to parse. Consider dropping the trailing clause:

Suggested change
Regarding to [Pricing](/pricing), operators are counted as half of a regular seat ([developers](#developer)) as long as they are operators in all workspaces they are members of. Operators are not set as the instance-level. On the billing side, 1 developer seat or 2 operator/[external JWT token](../../advanced/16_external_auth_with_jwt/index.mdx) seats count as 1 seat, and each external JWT token in use also counts as half a seat (same as an operator). There is no need to differentiate between developers, operators and external JWT tokens when purchasing the license.
Regarding to [Pricing](/pricing), operators are counted as half of a regular seat ([developers](#developer)) as long as they are operators in all workspaces they are members of. Operators are not set as the instance-level. On the billing side, 1 developer seat or 2 operator/[external JWT token](../../advanced/16_external_auth_with_jwt/index.mdx) seats count as 1 seat. There is no need to differentiate between developers, operators and external JWT tokens when purchasing the license.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying windmilldocs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 98a9833
Status: ✅  Deploy successful!
Preview URL: https://37d92c41.windmilldocs.pages.dev
Branch Preview URL: https://external-jwt-pricing.windmilldocs.pages.dev

View logs

@hcourdent hcourdent merged commit a83960a into main May 6, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant