From bb6695d08fc16b29c3aa2c4d9a6eeeda175a1165 Mon Sep 17 00:00:00 2001 From: eli Date: Wed, 30 Sep 2026 11:45:31 -0500 Subject: [PATCH 1/2] Remove internal working files that cite private-repo paths (PER-16650) - Remove docs-content-audit.md and plans/: internal working files, not part of the site, that cite source paths in private repos. - Reword seven comments and DESIGN.md that cited website source paths. - Add scripts/check-private-paths.mjs (npm run paths:private) to the build, so a private-repo path in a tracked file fails the Netlify build. Co-Authored-By: Claude Opus 5.5 --- DESIGN.md | 2 +- STYLE_GUIDE.md | 2 +- docs-content-audit.md | 2237 ----------------- package.json | 3 +- plans/2026-09-15-docs-site-makeover.md | 481 ---- scripts/audit-a11y.mjs | 2 +- scripts/check-private-paths.mjs | 53 + .../diagrams/DecisionFlowDiagram.jsx | 2 +- src/components/diagrams/DiagramFrame.jsx | 2 +- .../diagrams/HybridDeploymentDiagram.jsx | 2 +- src/css/prism/dark.js | 2 +- src/css/tokens.scss | 2 +- src/data/site-links.js | 2 +- 13 files changed, 64 insertions(+), 2728 deletions(-) delete mode 100644 docs-content-audit.md delete mode 100644 plans/2026-09-15-docs-site-makeover.md create mode 100644 scripts/check-private-paths.mjs diff --git a/DESIGN.md b/DESIGN.md index f9205f7e..abb469ab 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -130,7 +130,7 @@ A calm reading surface on the www.permit.io brand. Warm paper-like light surface The source of truth is code: `src/css/tokens.scss` (brand and semantic tokens, with every contrast ratio), `src/css/base/_infima.scss` (tokens mapped onto Infima), `src/css/base/_typography.scss` (type scale), `src/css/components/*` (one partial per surface) and `src/css/prism/{light,dark}.js` (syntax colours). The frontmatter above mirrors those files; when they disagree, the SCSS wins and this file is stale. -**The Mirror Rule.** Brand tokens mirror `next-website/app/globals.css`. Change a brand value in both repos together, and record why here. +**The Mirror Rule.** Brand tokens mirror the www.permit.io website's global stylesheet. Change a brand value in both places together, and record why here. ## Colors diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md index 3cf5c00d..bf61dc02 100644 --- a/STYLE_GUIDE.md +++ b/STYLE_GUIDE.md @@ -130,7 +130,7 @@ Use these terms, spelled this way. ## Content quality rules (technical-docs-writing) -This section adds the stricter rules of the technical-docs-writing standard. Where it and the sections above disagree, the stricter rule wins, except for the owner decisions listed at the end of this section. The page-by-page scores live in `docs-content-audit.md` at the repo root. +This section adds the stricter rules of the technical-docs-writing standard. Where it and the sections above disagree, the stricter rule wins, except for the owner decisions listed at the end of this section. ### One reader and one content type per page diff --git a/docs-content-audit.md b/docs-content-audit.md deleted file mode 100644 index 207ad541..00000000 --- a/docs-content-audit.md +++ /dev/null @@ -1,2237 +0,0 @@ -# Docs content audit - -Audit of every routed page under `docs/` against the technical-docs-writing rubric (10 dimensions scored 0-2). A page is publishable with no zeroes and a total of at least 16/20. A page is world-class at 18/20 or higher. - -## Method - -1. Every routed page (`docs/**/*.mdx`, excluding `_` partials) was read in full. -2. Each page got one primary audience, one Diataxis content type, a 0-2 score on each dimension, and up to three concrete issues. -3. Pages rewritten in this PR are re-scored after the rewrite. The `Before` column shows the original total. - -Dimension keys: **Aud** audience fit, **Task** task success, **Type** content type discipline, **Acc** accuracy, **Str** structure, **Ex** examples, **Term** terminology, **AI** AI retrievability, **Mnt** maintenance, **Sty** style. - -## Score distribution - -| Total | Before | Current | -|---|---|---| -| 18-20 (world-class) | 2 | 242 | -| 16-17 (publishable) | 3 | 108 | -| 12-15 | 48 | 0 | -| 8-11 | 246 | 0 | -| 0-7 | 51 | 0 | -| **Publishable (>=16, no zeroes)** | 5 | 350 | -| **Mean total** | 9.7 | 18.0 | -| **Pages scored** | 350 | 350 | -## Folder summary - -| Folder | Pages | Mean before | Mean current | Publishable now | Lowest-scoring dimensions | -|---|---|---|---|---|---| -| `(root)` | 4 | 12.0 | 18.0 | 4 | mnt (3), aud (1), ai (1) | -| `ai-security` | 1 | 10.0 | 19.0 | 1 | ex (1) | -| `ai-security/access-request-mcp` | 3 | 7.3 | 18.0 | 3 | ex (3), type (1), mnt (1) | -| `ai-security/integrations` | 5 | 6.4 | 18.6 | 5 | ex (3), acc (2), task (1) | -| `api` | 7 | 10.7 | 18.6 | 7 | ex (3), acc (3), mnt (2) | -| `api/elements` | 4 | 6.8 | 18.0 | 4 | ex (2), type (2), mnt (2) | -| `api/examples` | 7 | 11.9 | 18.3 | 7 | mnt (4), ex (3), term (3) | -| `api/rbac` | 2 | 8.0 | 18.5 | 2 | acc (1), str (1), ex (1) | -| `api/rebac` | 1 | 11.0 | 18.0 | 1 | ex (1), ai (1) | -| `api/rebac/groups` | 2 | 7.0 | 18.0 | 2 | aud (1), acc (1), mnt (1) | -| `api/working-with-abac` | 6 | 6.3 | 17.7 | 6 | acc (4), ex (4), task (3) | -| `authentication` | 6 | 6.8 | 17.2 | 6 | ex (5), mnt (4), task (3) | -| `authentication/auth0` | 3 | 8.3 | 17.7 | 3 | ex (3), mnt (2), acc (1) | -| `authentication/cognito` | 2 | 8.5 | 18.0 | 2 | mnt (1), acc (1), ex (1) | -| `authentication/stytch` | 1 | 6.0 | 19.0 | 1 | ex (1) | -| `concepts` | 5 | 12.0 | 17.8 | 5 | acc (4), task (2), ex (2) | -| `concepts/pdp` | 10 | 10.5 | 17.9 | 10 | acc (7), mnt (6), ex (5) | -| `embeddable-uis` | 8 | 9.2 | 17.2 | 8 | acc (6), ex (5), mnt (5) | -| `embeddable-uis/element` | 5 | 7.6 | 17.8 | 5 | ex (4), acc (3), mnt (2) | -| `getting-started` | 2 | 14.5 | 17.0 | 2 | acc (2), mnt (2), aud (1) | -| `how-to` | 3 | 7.7 | 17.7 | 3 | acc (2), ex (2), mnt (2) | -| `how-to/SDLC` | 3 | 8.0 | 16.7 | 3 | ex (3), task (2), type (2) | -| `how-to/build-policies` | 2 | 11.5 | 17.5 | 2 | aud (1), acc (1), mnt (1) | -| `how-to/build-policies/abac` | 6 | 9.7 | 19.2 | 6 | ex (2), mnt (2), task (1) | -| `how-to/build-policies/rbac` | 3 | 9.0 | 18.7 | 3 | ex (2), mnt (2) | -| `how-to/build-policies/rebac` | 2 | 7.5 | 19.5 | 2 | ai (1) | -| `how-to/deploy` | 3 | 10.7 | 17.7 | 3 | type (3), mnt (2), sty (1) | -| `how-to/deploy/cloud-hosts` | 6 | 10.3 | 17.7 | 6 | ex (4), mnt (4), str (4) | -| `how-to/deploy/on-prem` | 9 | 9.1 | 17.8 | 9 | acc (6), mnt (5), type (4) | -| `how-to/enforce-permissions` | 7 | 9.1 | 17.9 | 7 | ex (5), task (4), acc (4) | -| `how-to/enforce-permissions/url-mapping` | 4 | 9.0 | 17.0 | 4 | ex (4), mnt (3), type (1) | -| `how-to/manage-data` | 3 | 10.0 | 18.7 | 3 | task (1), acc (1), mnt (1) | -| `how-to/monitoring-pdps` | 1 | 10.0 | 16.0 | 1 | type (1), acc (1), ex (1) | -| `how-to/permit-cli` | 7 | 10.3 | 18.0 | 7 | ex (7), acc (3), task (1) | -| `how-to/policy-guard` | 2 | 9.5 | 17.0 | 2 | ex (2), mnt (2), acc (1) | -| `how-to/use-audit-logs` | 5 | 8.8 | 18.6 | 5 | ex (3), mnt (2), acc (2) | -| `how-to/use-audit-logs/errors` | 11 | 9.5 | 18.9 | 11 | ex (11), acc (1) | -| `integrations/GraphQL` | 2 | 8.5 | 18.5 | 2 | mnt (1), acc (1), ex (1) | -| `integrations/SCIM` | 3 | 11.3 | 19.0 | 3 | mnt (2), acc (1) | -| `integrations/database-access-control` | 1 | 13.0 | 16.0 | 1 | type (1), str (1), ex (1) | -| `integrations/feature-flagging` | 1 | 8.0 | 16.0 | 1 | acc (1), str (1), ai (1) | -| `integrations/gateways` | 4 | 9.2 | 17.5 | 4 | ex (4), acc (2), task (1) | -| `integrations/gitops` | 3 | 9.0 | 18.0 | 3 | term (1), mnt (1), aud (1) | -| `integrations/infra-as-code` | 1 | 12.0 | 17.0 | 1 | type (1), mnt (1), sty (1) | -| `integrations/permit-mcp` | 1 | 10.0 | 18.0 | 1 | ex (1), mnt (1) | -| `integrations/policy-engines` | 1 | 10.0 | 18.0 | 1 | task (1), acc (1) | -| `integrations/workflow-automation` | 1 | 9.0 | 18.0 | 1 | type (1), mnt (1) | -| `manage-your-account` | 6 | 9.2 | 17.2 | 6 | ex (5), mnt (5), type (2) | -| `modeling` | 7 | 9.3 | 17.4 | 7 | mnt (6), ex (4), task (3) | -| `overview` | 20 | 11.1 | 18.2 | 20 | mnt (11), acc (7), ex (5) | -| `permit-mcp-gateway` | 16 | 11.1 | 17.4 | 16 | mnt (16), acc (10), type (8) | -| `permit-mcp-gateway/demos` | 2 | 9.0 | 17.5 | 2 | mnt (2), acc (1), ex (1) | -| `permit-mcp-gateway/http-egress-proxy` | 8 | 11.2 | 17.6 | 8 | mnt (5), acc (4), term (4) | -| `quick-start` | 10 | 9.9 | 17.9 | 10 | mnt (10), sty (4), ex (3) | -| `sdk` | 2 | 10.0 | 17.0 | 2 | term (2), sty (1), acc (1) | -| `sdk/cpp` | 1 | 7.0 | 17.0 | 1 | task (1), ex (1), mnt (1) | -| `sdk/dotnet` | 1 | 10.0 | 16.0 | 1 | acc (1), ex (1), mnt (1) | -| `sdk/dotnet/role` | 6 | 10.7 | 18.8 | 6 | ex (6), sty (1) | -| `sdk/dotnet/tenant` | 4 | 10.5 | 19.0 | 4 | ex (4) | -| `sdk/dotnet/user` | 4 | 11.0 | 18.8 | 4 | ex (4), mnt (1) | -| `sdk/erlang` | 1 | 7.0 | 18.0 | 1 | task (1), ex (1) | -| `sdk/golang` | 1 | 9.0 | 16.0 | 1 | acc (1), ex (1), term (1) | -| `sdk/golang/resource` | 3 | 10.0 | 18.3 | 3 | mnt (3), ex (2) | -| `sdk/golang/role` | 4 | 9.2 | 18.2 | 4 | ex (4), mnt (3) | -| `sdk/golang/tenant` | 5 | 10.2 | 18.6 | 5 | mnt (4), ex (3) | -| `sdk/golang/user` | 8 | 10.0 | 18.6 | 8 | mnt (7), ex (4) | -| `sdk/java` | 1 | 10.0 | 18.0 | 1 | ex (1), mnt (1) | -| `sdk/java/resource` | 5 | 10.6 | 17.8 | 5 | ai (5), mnt (5), acc (1) | -| `sdk/java/role` | 8 | 10.9 | 18.0 | 8 | ai (8), mnt (7), acc (1) | -| `sdk/java/tenant` | 5 | 10.8 | 17.8 | 5 | ai (5), mnt (4), ex (1) | -| `sdk/java/user` | 5 | 10.6 | 18.2 | 5 | ai (5), mnt (3), acc (1) | -| `sdk/kotlin` | 1 | 7.0 | 17.0 | 1 | task (1), ex (1), mnt (1) | -| `sdk/nodejs` | 3 | 7.3 | 17.0 | 3 | task (2), ex (2), type (2) | -| `sdk/nodejs/relationship-tuple` | 1 | 9.0 | 19.0 | 1 | ai (1) | -| `sdk/nodejs/resource` | 3 | 9.7 | 17.7 | 3 | ex (3), ai (3), acc (1) | -| `sdk/nodejs/resource-instance` | 1 | 10.0 | 19.0 | 1 | ai (1) | -| `sdk/nodejs/role` | 7 | 9.9 | 17.9 | 7 | ex (7), ai (7), acc (1) | -| `sdk/nodejs/sync-policy-script` | 1 | 10.0 | 16.0 | 1 | type (1), ex (1), mnt (1) | -| `sdk/nodejs/tenant` | 6 | 10.2 | 18.3 | 6 | ai (5), ex (4), task (1) | -| `sdk/nodejs/user` | 5 | 10.4 | 18.2 | 5 | ex (4), ai (4), task (1) | -| `sdk/php` | 1 | 9.0 | 19.0 | 1 | mnt (1) | -| `sdk/python` | 3 | 10.0 | 18.3 | 3 | type (2), task (1), str (1) | -| `sdk/python/sync-policy-script` | 1 | 9.0 | 18.0 | 1 | ex (1), mnt (1) | -| `sdk/ruby` | 1 | 10.0 | 19.0 | 1 | type (1) | -| `sdk/ruby/user` | 1 | 9.0 | 18.0 | 1 | task (1), ex (1) | -| `updates-and-feedback` | 3 | 6.0 | 20.0 | 3 | all dimensions at 2 | - -## Lowest-scoring 40 pages (before) - -| # | Page | Before | Current | Top issues | -|---|---|---|---|---| -| 1 | `docs/api/working-with-abac/overview.mdx` | 3 | 16 | stub with duplicate 'Overview' H2 then H4, promised vocabulary never appears; says rules are 'part of' condition sets (wrong); 'now', 'Previously', 'new version' dated wording, no links to child pages | -| 2 | `docs/api/rbac/rbac-example.mdx` | 4 | 18 | resource JSON has double commas and second user curl lacks 'curl', so steps fail; opening sentence is broken editing residue ('RBAC API" and delete it below.') duplicated as H4; no section headings or verify check, we/let's, comments say 'user role' for operator | -| 3 | `docs/authentication/fusionauth.mdx` | 4 | 16 | 'coming soon' stub with only a personal GitHub repo (filipermit) and tracking link; no steps, embedded webinar only; emoji, 'play with', 'we did' | -| 4 | `docs/authentication/supertokens.mdx` | 4 | 15 | no intro; npm install before any clone step, repo link only at end, no env or API key wiring; personal repo (filipermit), old permitio/pdp image, webinar and screenshots; emoji, 'Enjoy the demo!', 'the above example' | -| 5 | `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | 5 | 14 | client.py Python blocks have collapsed whitespace (typing_extensionsimport, asyncdef) and wrong lang tags (shell/scss); interrupt resume code never shown, 'graph should not look like this', role child-can-order undefined; we/let's, em dashes, 'simple', many volatile screenshots | -| 6 | `docs/ai-security/integrations/langflow.mdx` | 5 | 13 | never explains installing Permit components in Langflow or minting test JWTs; docker command contains pasted 'bash CopyEdit' artifact, booking flow reuses info-flow screenshot 10.png, condition uses undefined resource.class, fake URLs api.flightpolicies.com; LangFlow/Langflow casing, we/let's, em dashes | -| 7 | `docs/api/rebac/groups/groups.mdx` | 5 | 16 | broken curl samples: curly quote in JSON, unquoted tenant key, blank lines inside continued commands, PUT path uses group_resource_type_key; inconsistent tenants (default vs business), 'team#member' vs teams, GET descriptions reference 'marketing' with placeholder paths; 'new and improved'/deprecated wording, redoc vs scalar links, 'Let's dive deeper', 'we', 'of course' | -| 8 | `docs/how-to/build-policies/policy-basics.mdx` | 5 | 14 | link to http://localhost:3000/integrations/gitops/github, stray Hebrew character, 'Roles exist on an organization level' contradicts environment-level roles; repeated '(Top Level in the UI)' link spam and User Management vs Directory vs members confusion; marketing intro ('power of a powerful', 'champions', 'extremely simple, yet vastly powerful') and 8 UI videos | -| 9 | `docs/how-to/build-policies/rebac/building-rebac-policies.mdx` | 5 | 15 | acronyms swapped: 'Relationship-Based Access Control (RBAC)' and 'Role-Based Access Control (ReBAC)', typo 'group.xe'; repeated H5 'UI Example' headings not self-contained, videos + YouTube; 'crux', 'robust', 'crucial', 'molding' | -| 10 | `docs/ai-security/integrations/openai-prompt-filtering.mdx` | 6 | 14 | classify() never implemented and users never created, so code cannot run; roles placed under Directory > Roles, tip claims container PDP needed for role-based permissions, broken link www.app.permit.io; ungrammatical opening sentence, dangling 'demonstrate how the system:', we/let's, em dashes | -| 11 | `docs/ai-security/integrations/pydantic-ai.mdx` | 6 | 15 | source link and clone path point to langchain-permit while resources link Permit-PydanticAI, PydanticAI links to a personal fork; attribute model inconsistent (test users use membership_tier/verified never defined, clearance high vs confidential, 'bookings' copied from flight demo), PERMIT_KEY vs PERMIT_API_KEY; 'powerful', 'full confidence', em dashes | -| 12 | `docs/api/elements/access-requests.mdx` | 6 | 18 | curl samples invalid (missing line continuations, trailing commas, missing braces) and filters passed as headers; tells reader to get API_SECRET_KEY but calls use login cookie; 'SDK Secret Key', 'Embeddable Elements', H3 before any H2, duplicates access-request-api.mdx | -| 13 | `docs/api/elements/operation_approval.mdx` | 6 | 18 | curl samples invalid and create body omits resource_instance that responses include; Redoc link points to Access-Requests tag, header 'element_id: ELEMENTS_CONFIG_ID' unexplained; 'SDK Secret Key'/API_SECRET_KEY terms, real-looking name maya@permit.io, init/login block duplicated from access-requests | -| 14 | `docs/api/working-with-abac/condition-set-rules.mdx` | 6 | 18 | stub: payload only, no endpoint, method, or verify; depends on sets defined on another page ('this particular example'); 'Let's remind ourselves', 'we will want' | -| 15 | `docs/api/working-with-abac/examples.mdx` | 6 | 15 | page starts at H3/H4 with a sentence as heading; 'not': ['part-time'] contradicts operator syntax, Stanford never modeled, availability as string array; no endpoint or verify, 'lets', 'our' | -| 16 | `docs/authentication/auth0/permit-integration.mdx` | 6 | 16 | link to http://localhost:3000 demo; role assignment code redeclares 'role', uses undefined permitUserObj/tenantKey, check without await; Auth0 Action steps duplicated verbatim from demo page, empty 'Getting Started' H2, 'easily', 'great blog post', 'Let's test it!' | -| 17 | `docs/authentication/hankopermit.mdx` | 6 | 16 | 'leading authorization platform' claim; ABAC steps contradict (new user 'should not be able to delete' then 'should also be able to delete'), 'same user who created the role'; broken samples (git clone , markdown link inside env value, untagged blocks), 14 screenshots with one reused, 'easily', 'great blog', 'we' | -| 18 | `docs/authentication/stytch/permit-integration.mdx` | 6 | 15 | sync code uses undefined userEmailId/tenantId/currentTenant and calls React hook useStytchUser in backend; redirect page imports Node 'stytch' SDK in the browser, REDIRECT_URL 'SEE_STEP_5' but covered in step 4; 'leading', 'robust', 'easily', 'him/his', typos | -| 19 | `docs/concepts/pdp/overview.mdx` | 6 | 12 | AuthZen curls use wrong paths (/v1/access/..., /v1/subjects) and invalid JSON trailing commas, Go snippet does not compile; mixes landing, how-to, caching and AuthZen reference with 'we', emoji, calendly link; H1 in body and Title Case headings | -| 20 | `docs/how-to/deploy/on-prem/installation.mdx` | 6 | 16 | 450 lines of internals before Step 1 and 'What happens' repeated twice; internal contradictions (help output lacks --gke, postgres 20GB vs 10Gi PVC, 'Infrastructure (10 services)' lists 11, '12 images' vs 35, Policy Sync required vs 'if configured'); 'As of January 2026', emojis, 'comprehensive', 'That's it!' | -| 21 | `docs/how-to/deploy/on-prem/prerequisites.mdx` | 6 | 17 | mixes architecture marketing, TLS config and troubleshooting into prereqs; inconsistent figures (35 vs 26 services, 51GB storage, '50-500 users'), repo sync called required then 'If you want to enable'; hype + emojis + CRITICAL caps, hardcoded usage numbers will rot | -| 22 | `docs/how-to/ownership.mdx` | 6 | 16 | ReBAC step says 'file is set as parent of folder' (reversed) and Bobs_Files#owner unexplained; typos (Upadte, Direcrory), let's/we, dash intro; 11 UI screenshots, concept + how-to muddled | -| 23 | `docs/integrations/gateways/kong.mdx` | 6 | 15 | docker command contains invisible U+2060 characters (not copy-runnable); '1-5 ms' claim, 'recent update', stale 'Copy SDK secret key' UI; 'seamlessly', 'easily', 'powerful', 'within minutes' | -| 24 | `docs/integrations/gitops/custom_policy.mdx` | 6 | 15 | final Rego invalid ('package package', import permit.rbac vs data.permit.rbac, else chain logic), untagged blocks; hardcoded 2023 dates and Cedar claim; let's/we, 'Were', emoji shortcode | -| 25 | `docs/overview/setup-attribute-based-access-control.mdx` | 6 | 15 | user set conditions (department=Engineering, training_status=certified) contradict scenario (R&D, completed); no enforcement or verify step, videos only with no code; vague UI paths ('Navigate to Dynamic Resource'), 'Imagine', 'master of ABAC' emoji | -| 26 | `docs/status.mdx` | 6 | 17 | page is only a scaled iframe with duplicate style prop (backgroundColor overwritten) and hardcoded 1080px width, poor on mobile; no text naming what is monitored (Cloud PDP, API, dashboard per description) or a direct status link for readers/agents; 'If you would like' wordy, ':::note info' misuse | -| 27 | `docs/updates-and-feedback/changelog.mdx` | 6 | 15 | stub with only an external link; 'here' link text; hype intro 'Explore the evolving journey' and 'our' | -| 28 | `docs/updates-and-feedback/feature-requests.mdx` | 6 | 16 | stub with only an external link; 'here' link text with random bold; marketing intro 'guiding the next wave of features we introduce' | -| 29 | `docs/updates-and-feedback/roadmap.mdx` | 6 | 16 | stub with only external link, roadmap on productlane while changelog/feature requests on Canny (possibly stale host); 'here' link text; hype 'glimpse into the future', 'innovations' | -| 30 | `docs/ai-security/access-request-mcp/implementation-guide.mdx` | 7 | 17 | mixes reference (env vars, tools) with a full FastAPI + CLI tutorial duplicated from food demo; CLI client code has broken indentation and undefined utils module; preview model gemini-2.5-flash-preview-04-17, 'powerful', 'easily', em dashes, vague verify step | -| 31 | `docs/ai-security/integrations/mongodb-rag.mdx` | 7 | 14 | ReBAC expanded as 'Role-Based Access Control (ReBAC)'; setup duplicated (Quickstart, Atlas setup, clone and .env repeated 3x) and quickstart says compose syncs everything while later steps run scripts manually; user ids inconsistent (carol/user_marketing_1 vs alice/bob), host scripts use http://permit-pdp:7000 | -| 32 | `docs/api/elements/access-request-api.mdx` | 7 | 18 | curl samples invalid (-data-raw single dash, no -X method, trailing commas, missing opening brace) and filters documented as headers not query params; near-verbatim duplicate of access-requests.mdx with the same response JSON repeated 6x; title 'Access Request API- API Only' and H1 'Use API KEY', unused imports | -| 33 | `docs/api/working-with-abac/building-conditions.mdx` | 7 | 15 | 'not' example is incoherent and INVALID age example says 48 vs code 40 with unverified 'Unbound Error'; repeated VALID/INVALID H4 headings not self-contained; 'we', 'Let's', 'important to note', Python True in js blocks | -| 34 | `docs/api/working-with-abac/condition-sets.mdx` | 7 | 16 | no endpoint or request to actually create a set; key mismatch private_repos vs private_repositories and parent example repeats parent condition, equals with arrays; relative .mdx link path likely broken, 'We will', 'Let's' | -| 35 | `docs/embeddable-uis/element-login.mdx` | 7 | 15 | broken code: Node init tab contains a Python import line, C# samples have unbalanced braces and no while body, JS loginUrl missing closing quote; loginAs params inconsistent (tenant vs tenantId), private-browsing sample returns {url: element_bearer_token}, dangling sentence 'Add with an authenticated session'; emojis, 'simple', 'We have', hyphen dashes, 'now compatible' dated language | -| 36 | `docs/embeddable-uis/element/audit-logs.mdx` | 7 | 16 | stub: no steps, config, or example beyond a screenshot and generic video; hype ('full control over your applications, enforcing security'); links to overview rather than embedding-elements | -| 37 | `docs/embeddable-uis/element/user-management.mdx` | 7 | 15 | no configuration steps or example, only concepts plus links; 'Effortlessly', em dash in 'straightforward-assign', 'valuable feedback'; H3 headings with colons and Q&A bold labels | -| 38 | `docs/embeddable-uis/webhooks.mdx` | 7 | 16 | 'Current flow' vs 'new approve invite flow' dated language, unclear which flow is live; no signature verification detail or handler example, schemas in pseudo-Python; skipped levels (H4-H6 then H3), 'leverage', 'array of functionalities', 'essentially' | -| 39 | `docs/how-to/build-policies/abac/patterns.mdx` | 7 | 15 | stale: 'Once we add ReBAC and groups natively to Permit.io' (ReBAC exists); 'ownership via user profile' lacks example, local PDP command uses 7767:7000 and :latest; 'easy', 'enjoy', hyphen dashes, H3 headings inside bullets | -| 40 | `docs/how-to/deploy/on-prem/quick-start.mdx` | 7 | 17 | description says 5-10 minutes, body says 10-15; nested 'Step 1/2/3' inside Step 2 makes headings ambiguous; uses --gke flag missing from installer help, no download source, emojis and 'just a few minutes' | - -## Upgraded pages - -| Page | Before | After | -|---|---|---| -| `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | 5 | 19 | -| `docs/ai-security/access-request-mcp/implementation-guide.mdx` | 7 | 17 | -| `docs/ai-security/access-request-mcp/overview.mdx` | 10 | 18 | -| `docs/ai-security/framework.mdx` | 10 | 19 | -| `docs/ai-security/integrations/langchain.mdx` | 8 | 19 | -| `docs/ai-security/integrations/langflow.mdx` | 5 | 17 | -| `docs/ai-security/integrations/mongodb-rag.mdx` | 7 | 20 | -| `docs/ai-security/integrations/openai-prompt-filtering.mdx` | 6 | 18 | -| `docs/ai-security/integrations/pydantic-ai.mdx` | 6 | 19 | -| `docs/api/api-reference.mdx` | 13 | 18 | -| `docs/api/api-with-cli.mdx` | 10 | 19 | -| `docs/api/background-tasks.mdx` | 11 | 19 | -| `docs/api/elements/access-request-api.mdx` | 7 | 18 | -| `docs/api/elements/access-requests.mdx` | 6 | 18 | -| `docs/api/elements/operation_approval.mdx` | 6 | 18 | -| `docs/api/elements/overview.mdx` | 8 | 18 | -| `docs/api/examples/autopopulate-actions.mdx` | 12 | 17 | -| `docs/api/examples/create-tenant.mdx` | 12 | 19 | -| `docs/api/examples/filter-relationship-tuple.mdx` | 12 | 19 | -| `docs/api/examples/filter-role-associations.mdx` | 12 | 19 | -| `docs/api/examples/filter-users.mdx` | 12 | 17 | -| `docs/api/examples/get-project-and-env.mdx` | 12 | 19 | -| `docs/api/examples/list-user-permissions.mdx` | 11 | 18 | -| `docs/api/pdp-api-reference.mdx` | 12 | 19 | -| `docs/api/pdp-statistics.mdx` | 11 | 19 | -| `docs/api/pdp-webhooks.mdx` | 10 | 18 | -| `docs/api/rbac/disable-rebac-to-increase-performance.mdx` | 12 | 19 | -| `docs/api/rbac/rbac-example.mdx` | 4 | 18 | -| `docs/api/rebac/groups/groups-ui.mdx` | 9 | 17 | -| `docs/api/rebac/groups/groups.mdx` | 5 | 19 | -| `docs/api/rebac/rebac-api-calls.mdx` | 11 | 18 | -| `docs/api/v2-migration-guide.mdx` | 8 | 18 | -| `docs/api/working-with-abac/building-conditions.mdx` | 7 | 18 | -| `docs/api/working-with-abac/condition-set-rules.mdx` | 6 | 18 | -| `docs/api/working-with-abac/condition-sets.mdx` | 7 | 16 | -| `docs/api/working-with-abac/examples.mdx` | 6 | 20 | -| `docs/api/working-with-abac/operators.mdx` | 9 | 18 | -| `docs/api/working-with-abac/overview.mdx` | 3 | 16 | -| `docs/authentication/auth0/auth0-demo-app.mdx` | 8 | 19 | -| `docs/authentication/auth0/auth0-sync-script.mdx` | 11 | 18 | -| `docs/authentication/auth0/permit-integration.mdx` | 6 | 16 | -| `docs/authentication/cognito/cognito-demo-app.mdx` | 8 | 19 | -| `docs/authentication/cognito/permit-integration.mdx` | 9 | 17 | -| `docs/authentication/fusionauth.mdx` | 4 | 16 | -| `docs/authentication/hankopermit.mdx` | 6 | 16 | -| `docs/authentication/logto.mdx` | 11 | 16 | -| `docs/authentication/permit-and-authentication.mdx` | 8 | 19 | -| `docs/authentication/stytch/permit-integration.mdx` | 6 | 19 | -| `docs/authentication/supertokens.mdx` | 4 | 20 | -| `docs/authentication/your-authentication.mdx` | 8 | 16 | -| `docs/concepts/control-plane-and-data-plane.mdx` | 14 | 18 | -| `docs/concepts/deployment-options.mdx` | 14 | 18 | -| `docs/concepts/differentiator-checklist.mdx` | 13 | 20 | -| `docs/concepts/multi-tenant-authorization.mdx` | 10 | 17 | -| `docs/concepts/oss-fallback.mdx` | 9 | 16 | -| `docs/concepts/pdp/cloud-pdp-benchmarks.mdx` | 14 | 18 | -| `docs/concepts/pdp/cloud-pdp-capabilities.mdx` | 11 | 17 | -| `docs/concepts/pdp/configuration.mdx` | 12 | 17 | -| `docs/concepts/pdp/nexus-pdp-architecture.mdx` | 12 | 18 | -| `docs/concepts/pdp/nexus-pdp-configuration.mdx` | 11 | 18 | -| `docs/concepts/pdp/nexus-pdp-deployment.mdx` | 9 | 20 | -| `docs/concepts/pdp/nexus-pdp-feature-parity.mdx` | 11 | 18 | -| `docs/concepts/pdp/nexus-pdp-how-it-works.mdx` | 10 | 17 | -| `docs/concepts/pdp/nexus-pdp.mdx` | 9 | 17 | -| `docs/concepts/pdp/overview.mdx` | 6 | 19 | -| `docs/embeddable-uis/element-login.mdx` | 7 | 18 | -| `docs/embeddable-uis/element/access-request.mdx` | 8 | 17 | -| `docs/embeddable-uis/element/approval-management.mdx` | 8 | 17 | -| `docs/embeddable-uis/element/audit-logs.mdx` | 7 | 16 | -| `docs/embeddable-uis/element/operation-approval.mdx` | 8 | 20 | -| `docs/embeddable-uis/element/user-management.mdx` | 7 | 19 | -| `docs/embeddable-uis/email-configuration-and-templates.mdx` | 9 | 17 | -| `docs/embeddable-uis/embedding-elements.mdx` | 9 | 17 | -| `docs/embeddable-uis/overview.mdx` | 11 | 19 | -| `docs/embeddable-uis/permission-levels.mdx` | 10 | 18 | -| `docs/embeddable-uis/troubleshooting.mdx` | 11 | 17 | -| `docs/embeddable-uis/user-preview.mdx` | 10 | 16 | -| `docs/embeddable-uis/webhooks.mdx` | 7 | 16 | -| `docs/faq.mdx` | 10 | 20 | -| `docs/getting-started/ai-support.mdx` | 18 | 17 | -| `docs/getting-started/slack-support.mdx` | 11 | 17 | -| `docs/home.mdx` | 16 | 17 | -| `docs/how-to/SDLC/CI-CD.mdx` | 8 | 16 | -| `docs/how-to/SDLC/authz-testing.mdx` | 8 | 17 | -| `docs/how-to/SDLC/modeling-implementation-components.mdx` | 8 | 17 | -| `docs/how-to/build-policies/abac/building-abac-policy.mdx` | 8 | 20 | -| `docs/how-to/build-policies/abac/components.mdx` | 12 | 19 | -| `docs/how-to/build-policies/abac/defining-attributes.mdx` | 9 | 19 | -| `docs/how-to/build-policies/abac/overview.mdx` | 11 | 18 | -| `docs/how-to/build-policies/abac/patterns.mdx` | 7 | 19 | -| `docs/how-to/build-policies/abac/time-based-role.mdx` | 11 | 20 | -| `docs/how-to/build-policies/overview.mdx` | 18 | 17 | -| `docs/how-to/build-policies/policy-basics.mdx` | 5 | 18 | -| `docs/how-to/build-policies/rbac/building-rbac-policy.mdx` | 8 | 20 | -| `docs/how-to/build-policies/rbac/components.mdx` | 9 | 18 | -| `docs/how-to/build-policies/rbac/overview.mdx` | 10 | 18 | -| `docs/how-to/build-policies/rebac/building-rebac-policies.mdx` | 5 | 19 | -| `docs/how-to/build-policies/rebac/overview.mdx` | 10 | 20 | -| `docs/how-to/bulk-operations.mdx` | 8 | 17 | -| `docs/how-to/deploy/cloud-hosts/aws-ecs-fargate.mdx` | 8 | 18 | -| `docs/how-to/deploy/cloud-hosts/gcp-cloud-run.mdx` | 12 | 18 | -| `docs/how-to/deploy/cloud-hosts/helm.mdx` | 12 | 19 | -| `docs/how-to/deploy/cloud-hosts/kubernetes-raw.mdx` | 10 | 18 | -| `docs/how-to/deploy/cloud-hosts/pulumi.mdx` | 10 | 16 | -| `docs/how-to/deploy/cloud-hosts/terraform.mdx` | 10 | 17 | -| `docs/how-to/deploy/deploy-to-production.mdx` | 9 | 18 | -| `docs/how-to/deploy/offline-mode.mdx` | 14 | 17 | -| `docs/how-to/deploy/on-prem/change-organization-tier.mdx` | 12 | 17 | -| `docs/how-to/deploy/on-prem/installation.mdx` | 6 | 16 | -| `docs/how-to/deploy/on-prem/landing.mdx` | 9 | 16 | -| `docs/how-to/deploy/on-prem/management.mdx` | 9 | 20 | -| `docs/how-to/deploy/on-prem/pdp-deployment.mdx` | 13 | 17 | -| `docs/how-to/deploy/on-prem/prerequisites.mdx` | 6 | 17 | -| `docs/how-to/deploy/on-prem/quick-start.mdx` | 7 | 17 | -| `docs/how-to/deploy/on-prem/reference.mdx` | 8 | 20 | -| `docs/how-to/deploy/on-prem/troubleshooting.mdx` | 12 | 20 | -| `docs/how-to/deploy/overview.mdx` | 9 | 18 | -| `docs/how-to/enforce-permissions/all-tenants-check.mdx` | 11 | 17 | -| `docs/how-to/enforce-permissions/authorized-users.mdx` | 8 | 17 | -| `docs/how-to/enforce-permissions/bulk-check.mdx` | 11 | 18 | -| `docs/how-to/enforce-permissions/check.mdx` | 10 | 17 | -| `docs/how-to/enforce-permissions/data-filtering.mdx` | 7 | 20 | -| `docs/how-to/enforce-permissions/list-role-assignments.mdx` | 9 | 17 | -| `docs/how-to/enforce-permissions/url-mapping/configuring-jwks.mdx` | 10 | 18 | -| `docs/how-to/enforce-permissions/url-mapping/fetching-jwks.mdx` | 8 | 18 | -| `docs/how-to/enforce-permissions/url-mapping/regex-url-mapping-check.mdx` | 9 | 16 | -| `docs/how-to/enforce-permissions/url-mapping/url-mapping-check.mdx` | 9 | 16 | -| `docs/how-to/enforce-permissions/user-permissions.mdx` | 8 | 19 | -| `docs/how-to/manage-data/loading-data.mdx` | 9 | 17 | -| `docs/how-to/manage-data/local-facts-uploader.mdx` | 12 | 19 | -| `docs/how-to/manage-data/use-external-data-source.mdx` | 9 | 20 | -| `docs/how-to/monitoring-pdps/monitoring-pdps.mdx` | 10 | 16 | -| `docs/how-to/ownership.mdx` | 6 | 16 | -| `docs/how-to/permit-cli/permit-cli-api.mdx` | 11 | 18 | -| `docs/how-to/permit-cli/permit-cli-envs.mdx` | 12 | 18 | -| `docs/how-to/permit-cli/permit-cli-gitops.mdx` | 7 | 17 | -| `docs/how-to/permit-cli/permit-cli-pdp.mdx` | 12 | 19 | -| `docs/how-to/permit-cli/permit-cli-policy.mdx` | 9 | 17 | -| `docs/how-to/permit-cli/permit-cli-test.mdx` | 12 | 19 | -| `docs/how-to/permit-cli/permit-cli.mdx` | 9 | 18 | -| `docs/how-to/policy-guard/policy_guard.mdx` | 10 | 17 | -| `docs/how-to/policy-guard/policy_guard_api.mdx` | 9 | 17 | -| `docs/how-to/sync-users.mdx` | 9 | 20 | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | 8 | 19 | -| `docs/how-to/use-audit-logs/debug-mode.mdx` | 9 | 18 | -| `docs/how-to/use-audit-logs/errors/cloud_pdp_not_supporting_abac.mdx` | 7 | 19 | -| `docs/how-to/use-audit-logs/errors/no_matching_resourcesets.mdx` | 9 | 19 | -| `docs/how-to/use-audit-logs/errors/no_matching_rules.mdx` | 10 | 18 | -| `docs/how-to/use-audit-logs/errors/no_matching_usersets.mdx` | 10 | 19 | -| `docs/how-to/use-audit-logs/errors/no_permission.mdx` | 9 | 19 | -| `docs/how-to/use-audit-logs/errors/no_role_in_tenant.mdx` | 10 | 19 | -| `docs/how-to/use-audit-logs/errors/no_such_action.mdx` | 9 | 19 | -| `docs/how-to/use-audit-logs/errors/no_such_resource.mdx` | 10 | 19 | -| `docs/how-to/use-audit-logs/errors/no_such_tenant.mdx` | 10 | 19 | -| `docs/how-to/use-audit-logs/errors/no_user_roles.mdx` | 10 | 19 | -| `docs/how-to/use-audit-logs/errors/user_not_synced.mdx` | 10 | 19 | -| `docs/how-to/use-audit-logs/logs-forwarder.mdx` | 9 | 19 | -| `docs/how-to/use-audit-logs/troubleshooting.mdx` | 9 | 18 | -| `docs/how-to/use-audit-logs/types-and-filtering.mdx` | 9 | 19 | -| `docs/integrations/GraphQL/apollo_server.mdx` | 10 | 19 | -| `docs/integrations/GraphQL/overview.mdx` | 7 | 18 | -| `docs/integrations/SCIM/EntraID.mdx` | 12 | 19 | -| `docs/integrations/SCIM/OKTA.mdx` | 10 | 18 | -| `docs/integrations/SCIM/SCIM_overview.mdx` | 12 | 20 | -| `docs/integrations/database-access-control/trino-integration.mdx` | 13 | 16 | -| `docs/integrations/feature-flagging/casl.mdx` | 8 | 16 | -| `docs/integrations/gateways/aws-api-gateway.mdx` | 10 | 16 | -| `docs/integrations/gateways/kong.mdx` | 6 | 19 | -| `docs/integrations/gateways/nginx.mdx` | 11 | 19 | -| `docs/integrations/gateways/overview.mdx` | 10 | 16 | -| `docs/integrations/gitops/custom_policy.mdx` | 6 | 20 | -| `docs/integrations/gitops/github.mdx` | 12 | 18 | -| `docs/integrations/gitops/overview.mdx` | 9 | 16 | -| `docs/integrations/infra-as-code/terraform-provider.mdx` | 12 | 17 | -| `docs/integrations/permit-mcp/overview.mdx` | 10 | 18 | -| `docs/integrations/policy-engines/overview.mdx` | 10 | 18 | -| `docs/integrations/workflow-automation/n8n.mdx` | 9 | 18 | -| `docs/manage-your-account/creating-environments.mdx` | 10 | 17 | -| `docs/manage-your-account/permit-logs.mdx` | 9 | 17 | -| `docs/manage-your-account/projects-and-env.mdx` | 7 | 18 | -| `docs/manage-your-account/workspace-api.mdx` | 10 | 17 | -| `docs/manage-your-account/workspace-settings.mdx` | 9 | 18 | -| `docs/manage-your-account/workspace-usage.mdx` | 10 | 16 | -| `docs/modeling/feature-flagging.mdx` | 9 | 19 | -| `docs/modeling/food-delivery-system-example-using-nuxt.mdx` | 10 | 18 | -| `docs/modeling/google-drive.mdx` | 11 | 17 | -| `docs/modeling/mesa-verde.mdx` | 8 | 17 | -| `docs/modeling/other-code-examples.mdx` | 8 | 16 | -| `docs/modeling/pink-mobile.mdx` | 10 | 17 | -| `docs/modeling/rebac-GHC.mdx` | 9 | 18 | -| `docs/overview/access-requests-and-approvals.mdx` | 8 | 16 | -| `docs/overview/advanced-authorization-queries.mdx` | 10 | 20 | -| `docs/overview/best-practices.mdx` | 15 | 18 | -| `docs/overview/configure-your-first-rbac-policy.mdx` | 11 | 18 | -| `docs/overview/connecting-your-app.mdx` | 14 | 18 | -| `docs/overview/create-a-rebac-policy.mdx` | 8 | 19 | -| `docs/overview/get-api-key.mdx` | 15 | 18 | -| `docs/overview/glossary.mdx` | 12 | 16 | -| `docs/overview/how-does-it-work.mdx` | 16 | 17 | -| `docs/overview/local-authorization-microservice.mdx` | 10 | 17 | -| `docs/overview/perform-a-local-policy-check.mdx` | 9 | 17 | -| `docs/overview/perform-policy-check-with-cloud-pdp.mdx` | 10 | 19 | -| `docs/overview/run-pdp.mdx` | 12 | 18 | -| `docs/overview/setup-attribute-based-access-control.mdx` | 6 | 19 | -| `docs/overview/sync-application-data-into-permit.mdx` | 9 | 20 | -| `docs/overview/sync-applications-data.mdx` | 11 | 19 | -| `docs/overview/sync-your-first-user-with-sdk.mdx` | 10 | 19 | -| `docs/overview/use-the-permit-api-and-sdk.mdx` | 9 | 20 | -| `docs/overview/walkthroughs-intro.mdx` | 15 | 18 | -| `docs/overview/why-permit.mdx` | 11 | 19 | -| `docs/permit-mcp-gateway/advanced-features.mdx` | 8 | 17 | -| `docs/permit-mcp-gateway/architecture.mdx` | 10 | 17 | -| `docs/permit-mcp-gateway/audit-logs.mdx` | 12 | 18 | -| `docs/permit-mcp-gateway/authentication-methods.mdx` | 15 | 17 | -| `docs/permit-mcp-gateway/consent-service.mdx` | 13 | 18 | -| `docs/permit-mcp-gateway/demos/linear-mcp-gateway.mdx` | 10 | 16 | -| `docs/permit-mcp-gateway/demos/n8n-linear-mcp-gateway.mdx` | 8 | 19 | -| `docs/permit-mcp-gateway/enterprise-deployment.mdx` | 10 | 17 | -| `docs/permit-mcp-gateway/guide.mdx` | 11 | 16 | -| `docs/permit-mcp-gateway/host-setup.mdx` | 9 | 16 | -| `docs/permit-mcp-gateway/http-egress-proxy/authorization.mdx` | 10 | 20 | -| `docs/permit-mcp-gateway/http-egress-proxy/cli.mdx` | 12 | 16 | -| `docs/permit-mcp-gateway/http-egress-proxy/connecting-agents.mdx` | 10 | 16 | -| `docs/permit-mcp-gateway/http-egress-proxy/credentials.mdx` | 10 | 17 | -| `docs/permit-mcp-gateway/http-egress-proxy/egress-rules.mdx` | 11 | 20 | -| `docs/permit-mcp-gateway/http-egress-proxy/index.mdx` | 11 | 18 | -| `docs/permit-mcp-gateway/http-egress-proxy/quickstart.mdx` | 13 | 18 | -| `docs/permit-mcp-gateway/http-egress-proxy/security.mdx` | 13 | 16 | -| `docs/permit-mcp-gateway/human-in-the-loop.mdx` | 9 | 18 | -| `docs/permit-mcp-gateway/index.mdx` | 15 | 18 | -| `docs/permit-mcp-gateway/managing-humans-and-agents.mdx` | 11 | 18 | -| `docs/permit-mcp-gateway/on-prem-installation.mdx` | 14 | 18 | -| `docs/permit-mcp-gateway/overview.mdx` | 8 | 17 | -| `docs/permit-mcp-gateway/permit-integration.mdx` | 12 | 17 | -| `docs/permit-mcp-gateway/platform.mdx` | 10 | 18 | -| `docs/permit-mcp-gateway/quickstart.mdx` | 10 | 19 | -| `docs/quick-start/aspnet.mdx` | 8 | 18 | -| `docs/quick-start/django.mdx` | 7 | 16 | -| `docs/quick-start/express.mdx` | 11 | 19 | -| `docs/quick-start/fastapi.mdx` | 11 | 18 | -| `docs/quick-start/flask.mdx` | 11 | 18 | -| `docs/quick-start/gin.mdx` | 10 | 19 | -| `docs/quick-start/nest.mdx` | 10 | 18 | -| `docs/quick-start/nextjs.mdx` | 10 | 17 | -| `docs/quick-start/rails.mdx` | 10 | 18 | -| `docs/quick-start/spring-boot.mdx` | 11 | 18 | -| `docs/quickstart.mdx` | 16 | 18 | -| `docs/sdk/cpp/quickstart-cpp.mdx` | 7 | 17 | -| `docs/sdk/dotnet/quickstart-dotnet.mdx` | 10 | 16 | -| `docs/sdk/dotnet/role/AssignRole.mdx` | 11 | 19 | -| `docs/sdk/dotnet/role/CreateRole.mdx` | 10 | 19 | -| `docs/sdk/dotnet/role/GetRole.mdx` | 11 | 18 | -| `docs/sdk/dotnet/role/ListAssignedRoles.mdx` | 10 | 19 | -| `docs/sdk/dotnet/role/ListRoles.mdx` | 11 | 19 | -| `docs/sdk/dotnet/role/UnassignRole.mdx` | 11 | 19 | -| `docs/sdk/dotnet/tenant/CreateTenant.mdx` | 10 | 19 | -| `docs/sdk/dotnet/tenant/DeleteTenant.mdx` | 11 | 19 | -| `docs/sdk/dotnet/tenant/GetTenant.mdx` | 11 | 19 | -| `docs/sdk/dotnet/tenant/UpdateTenant.mdx` | 10 | 19 | -| `docs/sdk/dotnet/user/CreateUser.mdx` | 11 | 19 | -| `docs/sdk/dotnet/user/DeleteUser.mdx` | 11 | 19 | -| `docs/sdk/dotnet/user/GetUser.mdx` | 11 | 19 | -| `docs/sdk/dotnet/user/SyncUser.mdx` | 11 | 18 | -| `docs/sdk/erlang/quickstart-erlang.mdx` | 7 | 18 | -| `docs/sdk/golang/quickstart-golang.mdx` | 9 | 16 | -| `docs/sdk/golang/resource/Create.mdx` | 10 | 18 | -| `docs/sdk/golang/resource/Delete.mdx` | 10 | 19 | -| `docs/sdk/golang/resource/Update.mdx` | 10 | 18 | -| `docs/sdk/golang/role/Create.mdx` | 9 | 18 | -| `docs/sdk/golang/role/Delete.mdx` | 10 | 19 | -| `docs/sdk/golang/role/Get.mdx` | 10 | 18 | -| `docs/sdk/golang/role/Update.mdx` | 8 | 18 | -| `docs/sdk/golang/tenant/Create.mdx` | 10 | 18 | -| `docs/sdk/golang/tenant/Delete.mdx` | 11 | 19 | -| `docs/sdk/golang/tenant/Get.mdx` | 10 | 18 | -| `docs/sdk/golang/tenant/List.mdx` | 10 | 19 | -| `docs/sdk/golang/tenant/Update.mdx` | 10 | 19 | -| `docs/sdk/golang/user/AssignResourceRole.mdx` | 11 | 19 | -| `docs/sdk/golang/user/AssignRole.mdx` | 11 | 19 | -| `docs/sdk/golang/user/Create.mdx` | 10 | 18 | -| `docs/sdk/golang/user/Delete.mdx` | 10 | 19 | -| `docs/sdk/golang/user/Get.mdx` | 9 | 18 | -| `docs/sdk/golang/user/GetAssignedRoles.mdx` | 9 | 19 | -| `docs/sdk/golang/user/SyncUser.mdx` | 11 | 18 | -| `docs/sdk/golang/user/UnassignRole.mdx` | 9 | 19 | -| `docs/sdk/java/quickstart-java.mdx` | 10 | 18 | -| `docs/sdk/java/resource/create.mdx` | 10 | 18 | -| `docs/sdk/java/resource/delete.mdx` | 11 | 18 | -| `docs/sdk/java/resource/get.mdx` | 10 | 17 | -| `docs/sdk/java/resource/list.mdx` | 11 | 18 | -| `docs/sdk/java/resource/update.mdx` | 11 | 18 | -| `docs/sdk/java/role/assign-role.mdx` | 11 | 18 | -| `docs/sdk/java/role/create.mdx` | 11 | 19 | -| `docs/sdk/java/role/delete.mdx` | 11 | 18 | -| `docs/sdk/java/role/get-assigned-roles.mdx` | 11 | 18 | -| `docs/sdk/java/role/get.mdx` | 10 | 17 | -| `docs/sdk/java/role/list.mdx` | 11 | 18 | -| `docs/sdk/java/role/unassign-role.mdx` | 11 | 18 | -| `docs/sdk/java/role/update.mdx` | 11 | 18 | -| `docs/sdk/java/tenant/create.mdx` | 11 | 18 | -| `docs/sdk/java/tenant/delete.mdx` | 11 | 18 | -| `docs/sdk/java/tenant/get.mdx` | 10 | 17 | -| `docs/sdk/java/tenant/list.mdx` | 11 | 18 | -| `docs/sdk/java/tenant/update.mdx` | 11 | 18 | -| `docs/sdk/java/user/create.mdx` | 10 | 18 | -| `docs/sdk/java/user/delete.mdx` | 11 | 19 | -| `docs/sdk/java/user/get.mdx` | 10 | 17 | -| `docs/sdk/java/user/list.mdx` | 11 | 18 | -| `docs/sdk/java/user/sync.mdx` | 11 | 19 | -| `docs/sdk/kotlin/quickstart-kotlin.mdx` | 7 | 17 | -| `docs/sdk/nodejs/all-tenants.mdx` | 7 | 17 | -| `docs/sdk/nodejs/bulk-requests-examples.mdx` | 7 | 17 | -| `docs/sdk/nodejs/quickstart-nodejs.mdx` | 8 | 17 | -| `docs/sdk/nodejs/relationship-tuple/list-relationship-tuples.mdx` | 9 | 19 | -| `docs/sdk/nodejs/resource-instance/list-resource-instances.mdx` | 10 | 19 | -| `docs/sdk/nodejs/resource/create-resource.mdx` | 9 | 18 | -| `docs/sdk/nodejs/resource/delete-resource.mdx` | 11 | 18 | -| `docs/sdk/nodejs/resource/update-resource.mdx` | 9 | 17 | -| `docs/sdk/nodejs/role/assign-role.mdx` | 9 | 18 | -| `docs/sdk/nodejs/role/create-role.mdx` | 9 | 18 | -| `docs/sdk/nodejs/role/delete-role.mdx` | 11 | 18 | -| `docs/sdk/nodejs/role/get-assigned-roles.mdx` | 11 | 18 | -| `docs/sdk/nodejs/role/get-role.mdx` | 11 | 18 | -| `docs/sdk/nodejs/role/unassign-role.mdx` | 9 | 18 | -| `docs/sdk/nodejs/role/update-role.mdx` | 9 | 17 | -| `docs/sdk/nodejs/sync-policy-script/sync-policy.mdx` | 10 | 16 | -| `docs/sdk/nodejs/tenant/create-tenant.mdx` | 9 | 18 | -| `docs/sdk/nodejs/tenant/delete-tenant.mdx` | 11 | 18 | -| `docs/sdk/nodejs/tenant/get-tenant.mdx` | 11 | 18 | -| `docs/sdk/nodejs/tenant/list-all-tenant-users.mdx` | 11 | 19 | -| `docs/sdk/nodejs/tenant/list-tenants.mdx` | 10 | 19 | -| `docs/sdk/nodejs/tenant/update-tenant.mdx` | 9 | 18 | -| `docs/sdk/nodejs/user/create-user.mdx` | 11 | 18 | -| `docs/sdk/nodejs/user/delete-user.mdx` | 11 | 18 | -| `docs/sdk/nodejs/user/get-user.mdx` | 10 | 18 | -| `docs/sdk/nodejs/user/list-users.mdx` | 10 | 19 | -| `docs/sdk/nodejs/user/sync-user.mdx` | 10 | 18 | -| `docs/sdk/permit-prisma-extension.mdx` | 12 | 18 | -| `docs/sdk/php/quickstart-php.mdx` | 9 | 19 | -| `docs/sdk/python/quickstart-python.mdx` | 10 | 19 | -| `docs/sdk/python/quickstart_python_sync.mdx` | 8 | 19 | -| `docs/sdk/python/sync-policy-script/sync-policy.mdx` | 9 | 18 | -| `docs/sdk/python/usage-example.mdx` | 12 | 17 | -| `docs/sdk/ruby/quickstart-ruby.mdx` | 10 | 19 | -| `docs/sdk/ruby/user/sync_user.mdx` | 9 | 18 | -| `docs/sdk/sdks-overview.mdx` | 8 | 16 | -| `docs/status.mdx` | 6 | 17 | -| `docs/updates-and-feedback/changelog.mdx` | 6 | 20 | -| `docs/updates-and-feedback/feature-requests.mdx` | 6 | 20 | -| `docs/updates-and-feedback/roadmap.mdx` | 6 | 20 | - -## Cross-page findings - -These problems span several pages. Fix them in batches, not page by page. - -### Broken or invalid code samples - -- `how-to/enforce-permissions/check.mdx`: stray `import { info } from "autoprefixer"` mid-page; the curl example passes a header with `-d`. -- `sdk/nodejs/all-tenants.mdx`, `sdk/nodejs/bulk-requests-examples.mdx`: curl uses `-D` (dump headers) instead of `-d`. -- Node.js reference pages (create/update resource, role, tenant; assign/unassign role) and `quick-start/express.mdx`, `quick-start/nest.mdx` pass `JSON.stringify(obj)` to SDK methods that take objects. -- Go reference pages: `role/Update` calls `Roles.Create`; `user/UnassignRole` calls `UnasignRole`; `GetAssignedRoles` passes a role key as the user. -- `api/rebac/groups/groups.mdx`, `api/elements/*`, `api/rbac/rbac-example.mdx`: invalid JSON and curl continuations. -- `ai-security/access-request-mcp/food-ordering-demo-example.mdx`: Python blocks lost their whitespace (`asyncdef`). -- `integrations/gateways/kong.mdx`: invisible U+2060 characters inside the docker command. -- `quick-start/django.mdx`, `quick-start/spring-boot.mdx`, `quick-start/nextjs.mdx`, `quick-start/gin.mdx`: undefined names, wrong routes, or wrong file locations. - -### Wrong definitions - -- `how-to/build-policies/rebac/building-rebac-policies.mdx` swaps the RBAC and ReBAC expansions. `ai-security/integrations/mongodb-rag.mdx` expands ReBAC as role-based. -- The framework quickstarts (`quick-start/*`) call a resource set "a ReBAC setup". A resource set is ABAC. -- The shared SDK quickstart partials say user data "never goes outside your system". Users are synced to the Permit control plane. - -### Duplicate or conflicting pages - -- `api/elements/access-request-api.mdx` and `api/elements/access-requests.mdx` are near copies. -- `overview/sync-application-data-into-permit.mdx`, `overview/sync-applications-data.mdx`, and `overview/sync-your-first-user-with-sdk.mdx` overlap. -- `authentication/your-authentication.mdx` and `authentication/permit-and-authentication.mdx` cover the same material. -- The eight framework guides in `quick-start/` share prose and reuse screenshots from other frameworks. -- `how-to/use-audit-logs/errors/no_matching_rules.mdx` and `how-to/use-audit-logs/errors/no_permission.mdx` have the same title and fix. -- On-prem pages disagree on the admin password secret, storage sizes, and whether Policy Sync is required. -- PDP health endpoint: `/health` on 7766 (`pdp-deployment`) vs `/healthy` on 7000 (`deploy/overview`). -- Permit MCP Gateway pages disagree on client setup (`mcp-remote` vs `url` key), trust-level consent flow, and whether the gateway is hosted-only. - -### Links and anchors - -- Several pages link to `/overview/connecting-your-app#1-get-your-permit-environment-api-key`, an anchor that comes from the imported partial `getting-started/_quickstart-parts/_quickstart_intro.mdx`. A heading change in that partial breaks every one of those links. Point them at `/overview/get-api-key`. -- Personal calendar links (`calendly.com/permit-io/demo`) appear on MCP gateway and deploy pages. The style guide requires `https://www.permit.io/demo`. -- Two Slack invite URLs are in use: `io.permit.io/slack` and `io.permit.io/docs-to-slack`. -- Links to `http://localhost:3000/...` in `how-to/build-policies/policy-basics.mdx` and `authentication/auth0/permit-integration.mdx`. -- Personal GitHub repos (`filipermit/*`, `eylonper/*`, `Tammibriggs/*`) linked as official examples. - -### Terminology drift - -- "SDK secret key", "API secret key", "API Key" instead of "API key". -- "Four Perimeter Model", "Four-Perimeter Framework", "4-Perimeter Framework". -- "container PDP", "Edge PDP", "sidecar", and "local PDP" used interchangeably. -- PDP service name `permitio-pdp` vs `permit-pdp` across the Helm, Pulumi, Terraform and raw Kubernetes pages. -- Real people's names and emails in SDK samples (`elonmusk@tesla.com`, company names), against the style guide. - -### Style patterns that cost the most points - -- Em dashes: the Permit MCP Gateway and HTTP egress proxy pages use them heavily (21 of 26 pages in those folders score 0 on style). -- "we", "let's", "simply", "easily", "powerful", "seamless", "robust" across tutorials and integration pages. -- Dated wording: "new", "recently", "coming soon", "on the roadmap", "as of January 2026", "in the near future". -- Headings that are not self-contained: bare H1s like "Create" or "list" in SDK reference pages, numbered "Step 3" headings, H1 to H3 jumps. - -## Consolidated owner-review list - -This list holds every claim in this pull request that needs your decision: a claim removed because no source could verify it, a claim changed where you may know the truth and may want the old wording back, a published number or fact the rewrite deleted, a claim a page still makes that nobody could verify, and a product or repository defect the docs now describe instead of the product fixing it. Claims corrected against a source that settles them, dead links, typos and style rewrites are not here; they stay in the Full claims log below, which keeps the per-batch detail and the reason for every change. The list holds 253 claims and 36 screenshot or media retakes. - -### Claims - -| Page | Claim as it was | What the page says now | Why the owner has to decide | -|---|---|---|---| -| `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | The seeded dish prices "Escargot $15.99, Foie Gras $19.99, Truffle Pasta $18.49, Pepperoni Pizza $10.99", and that `init_db()` marks Pizza Palace and Burger Bonanza child-allowed | Kept, unverified. | `init_db()` in `permitio/permit-mcp` was not fetchable from the environment. Reading that function settles the prices and the two child-allowed restaurants. | -| `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | "Head to **Project Settings** in the Permit dashboard and collect: `PROJECT_ID`, `ENV_ID`, `PERMIT_API_KEY`, `PERMIT_PDP_URL`" | Links to the pages that own each value. | The dashboard location could not be verified. A screenshot of the current Project Settings screen settles where each value lives. | -| `docs/ai-security/access-request-mcp/implementation-guide.mdx` | "`PROJECT_ID` ... Found in the Permit dashboard under Project Settings" and "`ACCESS_ELEMENTS_CONFIG_ID` ... Found under Elements > User Management" | Links to `/api/examples/get-project-and-env` and to the element's Get Code dialog. | Both UI locations could not be verified. A screenshot of each screen settles them. | -| `docs/ai-security/access-request-mcp/implementation-guide.mdx` | "Permit.io handles much of this [logging of all tool interactions] by default" | Kept only that permission checks appear in the audit log. | Nothing confirms that access request and approval tool calls are logged. One audit log sample from a demo run settles it. | -| `docs/ai-security/access-request-mcp/implementation-guide.mdx` | "Use Permit CLI's test generation features to simulate and validate scenarios." | Names `permit test generate e2e` and links it. | The command generates RBAC tests by default, and ReBAC coverage for this demo's model was not verified. Running it against the demo environment settles it. | -| `docs/ai-security/access-request-mcp/implementation-guide.mdx` | The example README claim that ReBAC "is not yet available in the cloud PDP" | The page says ABAC needs an Edge PDP and the Cloud PDP evaluates ReBAC. | The README in `permitio/permit-mcp` still carries the stale claim, so the repository and the page contradict each other until you fix the repository. | -| `docs/ai-security/integrations/langchain.mdx` | The `PermitEnsembleRetriever` note: the retriever sends the user as a key without attributes and each document as `{"id": ..., "type": ...}` | Kept, unverified. | It cites `langchain_permit/retrievers.py`, which was not fetchable. Reading that file settles it. | -| `docs/ai-security/integrations/langchain.mdx` | "PermitEnsembleRetriever ... filter documents based on Permit's ABAC policies" | Replaced with a warning that `resource.public` never reaches the PDP. | `langchain-permit` 0.1.4 sends `{"id","type"}` while `filter_objects` reads `key`/`attributes`. Decide whether to fix the library or keep the warning. | -| `docs/ai-security/integrations/langflow.mdx` | "The `permit-langflow` 0.1.0 package on PyPI pins `langflow==1.1.4.post1`." | Kept, unverified. | PyPI was not reachable from the environment. One metadata fetch settles it. | -| `docs/ai-security/integrations/langflow.mdx` | The tutorial's Permissions Check and Data Protection steps, presented as working | A `:::danger` block documenting two defects, and instructions to patch third-party code. | `permit-langflow-framework` never wires `validate_auth()` into `allowed_result`/`denied_result`, so every flow denies, and `data_protection.py` iterates a dict as objects and raises `AttributeError`. Fix the framework or accept that the page tells readers to patch it. | -| `docs/ai-security/integrations/langflow.mdx` | The Astra DB `flights` collection as a prerequisite | Kept, with no schema and no seed step. | The Parse DataFrame template expects `departure_city`, `arrival_city`, `departure_time`, `airline`, `flight_number`, `price` and `seats`. The tutorial needs a seed step from you. | -| `docs/ai-security/integrations/langflow.mdx` | Steps that add Text Input, Parse DataFrame, Filter Data and Astra Assistant Agent components | Kept as instructed steps. | Langflow moved the first three to legacy and lists no Astra Assistant Agent at all. Decide whether to rebuild the flow on current components. | -| `docs/ai-security/integrations/langflow.mdx` | "when multiple boxes are checked for an action, all conditions must be satisfied for the action to be allowed" | Removed. | It contradicts the Policy Editor semantics the rest of the docs describe, where each checked box is a separate grant, but nothing confirms which the product does. | -| `docs/ai-security/integrations/langflow.mdx` | "Or use Langflow Cloud (https://www.langflow.org/) to import your flows via JSON" | Removed. | No Langflow Cloud import path could be verified, and the tutorial ships no flows JSON. Supply one or the step stays out. | -| `docs/ai-security/integrations/langflow.mdx` | The Data Protection input "Filter IDs (optional): List of specific booking records to restrict" | Removed. | `components/data_protection.py` has no `filter_ids` input and the framework README claims one, so the README contradicts its own code. | -| `docs/ai-security/integrations/langflow.mdx` | The "sensitive data access" user set | Kept, with a warning that it matches no test user and both fixes. | The set compares the array attribute `membership_tier` with `equals`. Either the demo environment or the tutorial's attribute type is wrong. | -| `docs/ai-security/integrations/mongodb-rag.mdx` | "Immediate RAG Availability: Newly added files are ... immediately available for RAG queries" | Removed. | The watcher syncs to MongoDB, but Permit document instances appear only at startup or when `sync_documents.py` runs. Decide whether the watcher should sync to Permit too. | -| `docs/ai-security/integrations/openai-prompt-filtering.mdx` | "It allows offline development and testing" | Kept only "no network round trip to the Cloud PDP". | Offline operation could not be verified, because the PDP still syncs policy from the control plane. | -| `docs/ai-security/integrations/openai-prompt-filtering.mdx` | "Evaluated roles and attributes / Matched conditions and resource sets" as audit log contents | Reduced to user, action, resource and decision. | Which fields the audit log shows could not be verified. One decision log entry settles it. | -| `docs/ai-security/integrations/pydantic-ai.mdx` | The `pyproject.toml` `requires-python = ">=3.9"` and `.python-version` 3.13 claims | Kept, unverified. | Both files in `permitio/Permit-PydanticAI` were not fetchable. | -| `docs/ai-security/integrations/pydantic-ai.mdx` | That `opted_in_users` and `high_clearance_users` restrict a premium user's access | A warning stating the limitation, with corrective steps. | `example/config.py` grants `premium_user` `financial_advice:receive` and `financial_document:read` on the whole resource type, so neither set restricts that user. Fix `config.py` or keep the warning. | -| `docs/ai-security/integrations/pydantic-ai.mdx` | The `contains_advice` attribute as a boolean | The page documents the code. | `example/main.py` passes `str(contains_advice)` while `config.py` declares `contains_advice` as `bool`. Fix the example. | -| `docs/api/api-with-cli.mdx` | The rate-limit table: 40 req/min schema writes, 50 req/min members, 60 req/min DELETE, 100 req / 10 min bulk, 300 req/min writes, 1,000 req/min all requests | "Permit sets the limit values and can change them, so this page doesn't list them." | These numbers are published today and appear in no spec, pricing page or repository. Confirm them to restore the table. | -| `docs/api/api-with-cli.mdx` | "Only workspace owners see the API log. If the **API Log** tab isn't in **Settings**, ask the owner of your workspace." | Removed. | Nothing ties API Log visibility to the Workspace Owner role, and `docs/manage-your-account/permit-logs.mdx` still makes the same claim. Confirm it and both pages can agree. | -| `docs/api/api-with-cli.mdx` | "Only an environment API key works with the policy decision point (PDP) container." | The scope rule plus a link to the API key levels reference. | Corrected from PDP source, where `PDP_ORG_API_KEY` and `PDP_PROJECT_API_KEY` both work. `docs/manage-your-account/workspace-settings.mdx` still carries the old sentence and needs the same fix. | -| `docs/api/background-tasks.mdx` | "Background tasks may take a long time, up to 30 minutes" | Removed. | The bound is in no spec. Confirm a number to restore it. | -| `docs/api/elements/access-request-api.mdx` | "the `elements_config_id` refers to the ID of the user management element that is linked to the access request element" | "the ID or key of the element configuration" | The spec describes the field only as an elements config. Confirm which element config the facts-path endpoints expect. | -| `docs/api/elements/access-requests.mdx`, `docs/api/elements/operation_approval.mdx` | `USER_NOT_FOUND` when the user is not in the tenant, one tenant per session, the requester must belong to the tenant, non-reviewers see only their own requests, and the ticket `redirect_url` is a `get_cookie` URL | Kept, unverified. | All five carry over from the original pages. A run against the live endpoints settles them. | -| `docs/api/pdp-webhooks.mdx` | "If it doesn't work after several retries, Permit's support team will be notified automatically so they can look into the issue." | Removed. | The alerting could not be verified. Confirm it to restore the sentence. | -| `docs/api/pdp-webhooks.mdx` | "make sure your PDP is of at least version 0.2.24. This feature won't work with older PDPs." | Removed. | The GitHub code search was rate-limited, so the version floor could not be checked. Restore it if you confirm the release. | -| `docs/api/pdp-webhooks.mdx` | The Redoc link "https://api.permit.io/v2/redoc#tag/Webhooks" | Removed. | The endpoint answers, but the public OpenAPI spec has no webhooks path or tag, so the anchor cannot resolve. Decide whether to publish the endpoint in the spec. | -| `docs/api/rbac/disable-rebac-to-increase-performance.mdx` | "The updated configuration will take effect only when a new PDP instance is started" | "restart running PDPs" as a step, without "only when". | The source does not show whether running PDPs pick up `rebac_disabled` without a restart. | -| `docs/api/rbac/disable-rebac-to-increase-performance.mdx` | `rebac_disabled` as an environment setting | Kept, unverified. | It is confirmed in `permit-backend` but absent from the OpenAPI spec, where `EnvironmentUpdate.settings` is an untyped object. Decide whether to type it. | -| `docs/api/rebac/groups/groups-ui.mdx` | "Child groups inherit relationship configurations from parent groups" | Replaced with a link to the Groups API page. | The direction of inheritance is not derivable from the spec, which says only "This group will inherit the group's roles". | -| `docs/api/rebac/groups/groups.mdx` | "The name of this relation will be `team_group`" and "The name of this relation will be `group`" | Names removed. | Neither relation name is in the spec. Confirm the names Permit creates. | -| `docs/api/v2-migration-guide.mdx` | "a compatibility environment, `v2_global_env`, in the project `v1_global_project`" | The reader finds the environment from `GET /v2/projects` and its environments list and takes the key from the response. | The two names appear only in this docs page, while `permit-backend` test fixtures hold `v1compat_global_env` in an ordinary project. Confirm the real names and the code sample can carry them. | -| `docs/api/v2-migration-guide.mdx` | "The v2 API and the Permit dashboard show them in a compatibility environment that Permit created for them, and v2 PDPs ignore the objects in that environment." | A PDP serves the environment its `PDP_API_KEY` belongs to, and step 2 has the reader list that environment to confirm. | No compatibility-environment concept exists in the live spec, and nothing documents v2 PDPs ignoring an environment. The residual claim, that an environment the reader did not create holds v1's organization-scoped objects, still needs your confirmation. | -| `docs/api/v2-migration-guide.mdx` | "v2 SDKs work only with v2 PDPs, and v1 SDKs work only with v1 PDPs." | Upgrade a service's SDK and point it at the v2 PDP in the same change, and run both PDPs until every service has moved. | The compatibility rule could not be verified in any SDK or PDP repository. | -| `docs/api/v2-migration-guide.mdx` | "newly generated [API keys] are much shorter than before ... Existing API keys work normally, and new v2 keys work on v1 as expected" | Removed, kept "authenticate the same way". | Neither the key length nor the cross-version behavior could be verified. | -| `docs/api/v2-migration-guide.mdx` | "In v1, only users and roles can be organization-scoped." | Removed. Step 2 lists roles and users and says an empty list means nothing to move. | No public source states which v1 object types could be organization-scoped. | -| `docs/api/working-with-abac/building-conditions.mdx` | "This example is invalid because we specify the user.age to be between 15 and 18, but then set another condition to test for the age being greater than 48. This will throw an Unbound Error." (abridged) | The block is headed "Valid: two conditions on the same attribute" and the anchor `{#invalid-1}` stays. | The currently published page labels byte-identical JSON INVALID, and `ConditionSetCreate.conditions` is a free-form object in the spec, so nothing upstream settles it. It needs a live `POST /v2/schema/{proj}/{env}/condition_sets` plus an Edge PDP check. No page links to this page's anchors, so the anchor can be corrected safely once the flip is confirmed. | -| `docs/api/working-with-abac/building-conditions.mdx` | The `not` example showing `"not": [ ... ]` | "The value of `not` ... doesn't accept an array", matching `operators.mdx`. | The published `building-conditions` page and the published `operators.mdx` disagree with each other. Pick the form the backend accepts. | -| `docs/api/working-with-abac/building-conditions.mdx` | Examples using the `subject.*` and `environment.*` attribute prefixes | Rewritten with the documented `user.` prefix. | The prefixes appear in no SDK, PDP or backend source and in no other docs page, and `ConditionSet._sanitize_condition` accepts only `user.`, `resource.`, `tenant.`, `context.` and `role.`. If the backend takes them as aliases, they belong in `operators.mdx` as a documented alias list. | -| `docs/api/working-with-abac/examples.mdx` | The user set body | Uses `user.roles` with `array_contains`. | `docs/api/working-with-abac/condition-sets.mdx` still uses `{"user.role": {"equals": "employee"}}`, so the two pages now disagree. Pick one form and both pages can follow it. | -| `docs/authentication/auth0/auth0-demo-app.mdx` | No action matrix (this claim is new) | The matrix grants `put` and `patch` to `admin` and `manager` and denies them to `viewer`. | The five actions the demo sends are verified from the repository, but that role matrix is the page's own choice. Confirm it. | -| `docs/authentication/auth0/auth0-demo-app.mdx` | "the `userProvider` in `_app.tsx` redirects the user to the login page if they have not logged in" | Removed. | `UserProvider` only supplies user context. Confirm whether a redirect exists elsewhere. | -| `docs/authentication/auth0/auth0-demo-app.mdx`, `docs/authentication/cognito/cognito-demo-app.mdx` | Samples calling `permit.api.syncUser()` | Kept byte-identical. | `permit-node`'s `deprecated.d.ts` marks it "replaced with permit.api.users.sync()". The samples mirror the demo repositories the reader clones, and the same wording sits in prose on `docs/authentication/supertokens.mdx`. Update the repositories or accept the deprecated call. | -| `docs/authentication/auth0/auth0-sync-script.mdx` | Nothing (this fact is new) | After creating missing roles the script exits without syncing users, so the reader must rerun it. | The behavior is verified in the script. Decide whether to fix the script instead of documenting the rerun. | -| `docs/authentication/auth0/permit-integration.mdx` | "delete tasks immediately" | "without signing out and in again" | The propagation time was never measured. | -| `docs/authentication/cognito/cognito-demo-app.mdx` | That the repository's `/api/sync` route syncs the user | A warning that the route throws a ReferenceError, with the Directory workaround. | The defect is in `permitio/cognito-integration`, where `standalone_be/index.mjs` needs a `let payload` fix and an early return. Fix the repository and the warning goes. | -| `docs/authentication/cognito/cognito-demo-app.mdx` | The README instruction to run the frontend with `npm install` and serve it on port 8000 | The page says to serve the frontend on 8181. | The frontend has no `package.json`, and the backend listens on 8000 with CORS for 8181. Fix the README. | -| `docs/authentication/fusionauth.mdx`, `docs/authentication/supertokens.mdx` | Links to `github.com/filipermit/permit-x-fusionauth` and `github.com/filipermit/permit-x-supertokens` as the demo projects | Links kept, with a note that both pin `permitio` 0.0.5 and use SDK calls that no longer exist. | Both are personal repositories, last committed in 2022. Decide whether to move them under `permitio`, update them, or archive them. | -| `docs/authentication/fusionauth.mdx` | The demo repository as safe to clone and run | A warning to replace the committed credentials. | `filipermit/permit-x-fusionauth` commits a Permit API token, a FusionAuth client secret and an API key. Confirm those credentials are revoked. | -| `docs/authentication/logto.mdx` | "Logto signs webhook requests with the webhook's signing key" | Kept. | Taken from Logto's webhook docs and not re-fetched this session. | -| `docs/authentication/logto.mdx` | The demo's check-permission and webhook routes, presented without caveats | Warnings that the check-permission route trusts a `userId` query parameter and the webhook route does not verify Logto's signature. | Both are defects in the example app. Fix the example or keep the warnings. | -| `docs/authentication/permit-and-authentication.mdx` | "Compatible with All Authentication Standards: OAuth 2.0, OpenID Connect (OIDC), SAML, WS-Fed, Headers, mTLS" | Removed, replaced with the handoff mechanism. | WS-Fed and mTLS support is documented nowhere, and Permit checks take a user key while your app verifies tokens. Confirm the list. | -| `docs/authentication/permit-and-authentication.mdx` | IdP-managed roles have "no support for ReBAC" | Replaced with a tradeoff about runtime-granted roles. | SCIM and handoff code can write any role assignment, so the limitation could not be verified. | -| `docs/authentication/your-authentication.mdx` | "Permit.io measures usage through Monthly Active Users (MAUs) ... counted as a single MAU" | Removed. | The billing detail is volatile and is not an authentication task. Confirm where it belongs, most likely a pricing page. | -| `docs/concepts/deployment-options.mdx` | Full on-premise "delivered as Kubernetes Helm charts" and the light on-premise flow | Kept, unverified. | Consistent with the diagrams and the on-prem docs, but never traced in source. | -| `docs/concepts/multi-tenant-authorization.mdx` | "Use the selector at the top left to switch tenants, rename them, and create new ones." | Replaced with the Directory screen and All Tenants wording from `how-to/sync-users.mdx`. | The selector position and the rename and create actions could not be verified. A current screenshot settles them. | -| `docs/concepts/oss-fallback.mdx` | "use Permit's SDKs in passthrough mode, talking directly to the policy engines in your PDPs" | Removed. | No passthrough mode exists in any SDK or doc. Confirm whether the capability exists under another name. | -| `docs/concepts/pdp/cloud-pdp-benchmarks.mdx` | "Throughput scales near-linearly with concurrency, 10 concurrent requests yield roughly 10x throughput with minimal latency increase." | Removed. | It contradicts the page's own methodology, which measures the observed request rate rather than capacity. A capacity benchmark settles it. | -| `docs/concepts/pdp/cloud-pdp-benchmarks.mdx` | "P50 latency stays under 15 ms" and "suitable for latency-sensitive applications" | Restated from the tables as average P50 at or under 12 ms and average P99 under 50 ms, with no suitability claim. | Published figures changed. Confirm which numbers the page should carry. | -| `docs/concepts/pdp/cloud-pdp-capabilities.mdx` | "Any dashboards, filters, or exports you rely on today continue to work." | Removed. | Could not verify, and the wording is dated. | -| `docs/concepts/pdp/cloud-pdp-capabilities.mdx` | The Cloud PDP rate-limit table values, "ABAC not supported", "custom policy as code not supported", and Cloud PDP decision logs in the "same format" | Kept, unverified. | The Cloud PDP service configuration is not public. All four are consistent with `concepts/pdp/overview.mdx` and nothing else. | -| `docs/concepts/pdp/configuration.mdx` | `PDP_CONTROL_PLANE_PDP_DELTAS_API` "https://pdp-deltas.api.permit.io", `PDP_CONTROL_PLANE_RELAY_API` "https://opal-relay.api.permit.io", `PDP_CONTROL_PLANE_RELAY_JWT_TIER` "https://relay-jwt.api.permit.io" | "controlled by Permit" | Three published hostnames deleted, because the source defaults are localhost and the PDP receives the real values from the control plane. Confirm them to restore the defaults. | -| `docs/concepts/pdp/configuration.mdx` | `PDP_USE_NEW_AUTHORIZED_USERS` "This feature is controlled by the control plane." | Removed. | Could not verify. | -| `docs/concepts/pdp/configuration.mdx` | "_Added in PDP v0.9.0_" notes on `PDP_PORT`, `PDP_USE_NEW_AUTHORIZED_USERS`, `PDP_OPA_URL`, the cache and Horizon variables, and "_Added in PDP v0.9.4_" on `ALL_PROXY` | Kept, unverified. | `permitio/PDP` has no changelog, so only the variables' current existence is confirmed. Confirm the introducing releases. | -| `docs/concepts/pdp/configuration.mdx` | `PDP_OPA_CLIENT_QUERY_TIMEOUT` "0.9.0 and later: 0 means 0 seconds" | Kept, unverified. | The Python config confirms "0 means no timeout" for the old server, but the Rust behavior for 0 was not traced. | -| `docs/concepts/pdp/configuration.mdx` | `UVICORN_NUM_WORKERS` (default 1) and `GUNICORN_TIMEOUT` (default 600) | Moved under settings for PDP versions before v0.9.0, with the defaults unverified. | The current PDP starts Horizon without worker or Gunicorn flags, and the pre-0.9 defaults could not be verified. Confirm them or the section can go. | -| `docs/concepts/pdp/configuration.mdx` | `ALL_PROXY` "proxy must support HTTP/2 and WebSocket connections" and "TLS in TLS is not supported" | Kept, unverified. | Neither requirement was traced in source. | -| `docs/concepts/pdp/nexus-pdp-deployment.mdx` | "no ability to reach Permit's management API" for a compromised PDP | Kept only "holds one environment's data and credentials". | The binary has no Permit API client, but what a stolen `PDP_API_KEY` can do against `api.permit.io` could not be verified. Confirm the key's scope. | -| `docs/concepts/pdp/nexus-pdp-deployment.mdx` | "the container is killed mid-flush and the durable event store is corrupted, forcing a cold start on the next boot" | "killed before its event store finishes flushing" | The source shows only that SIGKILL can hit the leaf mid-flush. Corruption and a forced cold start were never verified. | -| `docs/concepts/pdp/nexus-pdp-deployment.mdx` | "Cold start can take minutes" and "minutes of startup" | "takes longer as your data grows" | No published figure exists, and the staging note in `config.rs` shows about 17 s for 306 MB. Supply a figure to restore a number. | -| `docs/concepts/pdp/nexus-pdp-feature-parity.mdx` | The "OpenTelemetry (OTLP traces, metrics, logs) \| ❌ \| 🚧 On the roadmap" row and its legend | Removed. | A published roadmap row deleted because the style guide forbids planned features. Decide whether the parity table should carry planned rows at all. | -| `docs/concepts/pdp/nexus-pdp-feature-parity.mdx` | "A check against a policy that uses condition sets, user sets, or resource sets returns a deny on Nexus PDP, not an error." | Kept, unverified. | Consistent with the ABAC design spec, where the stub `check/abac.rego` defaults to false, but never confirmed by a test. One check against a staging Nexus PDP settles it. | -| `docs/concepts/pdp/nexus-pdp-feature-parity.mdx` | "Kong and NGINX integrations" supported on the container PDP | Kept, unverified. | A pre-existing row that was not re-verified, and both integrations have open defects (see the Kong and NGINX rows below). | -| `docs/concepts/pdp/nexus-pdp-how-it-works.mdx` | "Bulk-loading pre-built database files is substantially faster than the container PDP's cold start" | Removed. | No comparative measurement exists. | -| `docs/concepts/pdp/nexus-pdp-how-it-works.mdx` | "Interest is held by the subscription's existence, not by an open connection; a PDP that is disconnected for minutes resumes exactly where it left off" | "resumes from its last acknowledged position" | The "minutes" retention bound is unverified. Supply the retention window. | -| `docs/concepts/pdp/nexus-pdp-how-it-works.mdx` | Last-writer-wins by (timestamp, transaction ID) with per-transaction atomicity | Kept, unverified. | Referenced as "the ordinary LWW guard" in the cloud-pdp ABAC spec, but the write-service source was not read. | -| `docs/concepts/pdp/overview.mdx` | "Custom cloud PDP deployments are available to enterprise tier customers" | A contact path without the tier. | The plan-tier claim is not verifiable from the docs or the pricing page. | -| `docs/embeddable-uis/element-login.mdx` | "In the backend route, return `ticket.element_bearer_token` in a JSON field named `url`" | Kept, unverified. | The field is real on the API response and `permit-js` does read `data.url`, but `element_bearer_token` is not declared in `permitio@2.7.6`'s `EmbeddedLoginRequestOutput` or `EmbeddedLoginRequestOutputWithContent`, so the sample does not type-check in TypeScript, and Python's typed client drops the field entirely. Add the field to the SDK type, or the sample casts. | -| `docs/embeddable-uis/element-login.mdx` | "This method needs `@permitio/permit-js` version 0.5.2 or later." | Kept, unverified. | 0.5.2 is the current release and does contain `supportsPrivateBrowser`, but the release that added it was not identified, so the floor may be higher than necessary. | -| `docs/embeddable-uis/element/approval-management.mdx` | "it is crucial to select the tenant" | The example has no `tenantKey`, and the reader sets it if the generated snippet includes it. | Confirm whether Approval Management iframes take `tenantKey`. | -| `docs/embeddable-uis/element/audit-logs.mdx` | The embed steps (create in the Elements screen, set permission levels, Generate Code, log in) | Kept, generalized from the other element pages. | The flow was not verified for this element type. Confirm the Audit Logs element uses the same one. | -| `docs/embeddable-uis/element/operation-approval.mdx` | The role assignment `transfer:transfer-1#_Reviewer_` | Kept, unverified. | The screenshot shows the role key `_reviewer_` in lowercase. Confirm the case Permit creates with the element. | -| `docs/embeddable-uis/element/user-management.mdx` | The on-screen label "End User Preview" | Kept, unverified. | The frontend components are named `ElementsPreview`. A screenshot of the current screen settles the label. | -| `docs/embeddable-uis/element/user-management.mdx` | The Webhook Notification row's list of webhook types | Kept as published. | It omits a third type, `role_assignment`. Confirm the full set. | -| `docs/embeddable-uis/element/user-management.mdx` | The iframe `src` pattern `https://embed.permit.io/?envId=&darkMode=false&tenantKey=` | Kept, taken from the sibling element pages. | It does not come from a User Management Generate Code dialog. Confirm the exact parameters for this element type. | -| `docs/embeddable-uis/element/user-management.mdx` | Nothing (this claim is new) | A Verify table describing what a Level 1, Level 2, Level 3 and Hidden-Roles-only user sees rendered. | The capabilities come from `permission-levels.mdx`, but the mapping from a capability to a visible control is an inference. Confirm it against the preview for each level. | -| `docs/embeddable-uis/email-configuration-and-templates.mdx` | "`{{ redirect_to }}` will be replaced with the URL that you filled in the Redirect To field" | "the invite link, built from the Redirect To URL" | What the template renders was not verified; the email link carries `invite_code`. | -| `docs/embeddable-uis/permission-levels.mdx` | "If a user opens the element with a role in Hidden Roles, the login **usually** fails with `INVALID_PERMISSION_LEVEL`" | Kept without "usually". | The behavior was not verified in source. | -| `docs/embeddable-uis/troubleshooting.mdx` | "the user will be redirected to the /login_elements page" | "A successful login makes a request to /login_elements" | Whether every login method produces that request is unverified; the diagram shows it for backend methods only. | -| `docs/embeddable-uis/user-preview.mdx` | The note about when the tenant dropdown appears | Kept, unverified. | Carried over from the original page with no source. | -| `docs/embeddable-uis/webhooks.mdx` | "Current flow" and "With the new approve invite flow applied" | Two neutrally named flows, "Invite creates the user" and "Invite requires approval", with both anchors kept. | Neither page says which flow is live or what setting selects it. Confirm the default and how it is chosen. | -| `docs/embeddable-uis/webhooks.mdx` | Nothing (this claim is new) | "The webhook type you receive tells you which flow applied: `create_user` or `invite_user`" | Inferred from the payload schemas, not verified in the sender source. | -| `docs/embeddable-uis/webhooks.mdx` | "we provide a input box so you can enter your secret, and use it to validate incoming data" | "Permit uses the secret as a bearer token to authenticate its requests", with an instruction to check the `Authorization` header. | The spec field is described as "An optional bearer token", but the `Authorization: Bearer` header format itself is inferred, not verified in the sender. | -| `docs/embeddable-uis/webhooks.mdx` | "If your endpoint fails to do this, the webhook may consider the delivery a failure and retry, causing unnecessary traffic" | Removed. | Retry behavior could not be verified. Confirm whether Permit retries. | -| `docs/faq.mdx` | "The free tier includes all features for up to 1,000 monthly active users, with no credit card required." | A link to the pricing page. | A published plan quota deleted, because quotas are volatile and not verifiable from any repository source. Decide whether the docs carry quotas at all. | -| `docs/faq.mdx`, `docs/getting-started/slack-support.mdx` | The Slack invite `https://io.permit.io/docs-to-slack` | Kept on these pages, while `STYLE_GUIDE.md` and other pages use `https://io.permit.io/slack`. | Both URLs return 200 and meta-refresh to the same invite, and `docs-to-slack` looks like the tracked link for docs. Pick one URL and it can be applied site-wide. | -| `docs/getting-started/_quickstart-parts/_quickstart_golang.mdx` | The heading "Full app example (includes ABAC RBAC and terraform )" | Kept only the verified Terraform configuration. | ABAC and RBAC coverage is not in the `permit-go-example` README. Confirm what the example covers. | -| `docs/getting-started/_quickstart-parts/_quickstart_intro.mdx` | A Node.js Cloud PDP snippet inside step 2 | Kept, and it renders for all eight consuming pages. | Python and Ruby readers meet JavaScript before their own language. Removing the snippet lifts the three SDK quickstarts from 19 to 20, but it deletes an existing sample from a partial shared by eight pages. | -| `docs/getting-started/_quickstart-parts/_quickstart_java.mdx` | "Example application using Spring framework" for `permit-java-example` | Removed. | The README describes "a simple blog application" and names no framework. Confirm the framework. | -| `docs/getting-started/_quickstart-parts/_quickstart_nodejs.mdx`, `_quickstart_python.mdx` | "There attributes are merged (and override) user and resource attributes that were persisted to the permit API." | Removed. | Merge and override semantics could not be verified in any SDK or doc. | -| `docs/getting-started/_quickstart-parts/_quickstart_python.mdx`, `_quickstart_python_sync.mdx` | The sample user `john@smith.com` in code and prose | Kept byte-identical. | The style guide asks for `john@permit.io`, `sam@permit.io` or an `example.com` address, and the Ruby partial already complies. The change touches code samples. | -| `docs/getting-started/_quickstart-parts/_quickstart_python_sync.mdx` | The full example pinning `permit==1.0.0rc1` and calling `permit.write()` | Kept with a warning. | The current `permit` package is 2.8.3 and has no `write()`. Approve the code fix and the warning goes. | -| `docs/getting-started/_quickstart-parts/_quickstart_{nodejs,python,python_sync,golang,java,dotnet,ruby}.mdx` | "You can also pass the entire decoded JWT, to include attributes about the user." | Removed. | SDK `check()` signatures take a user key or an object with `key` and `attributes`, not a JWT. Confirm whether a JWT is accepted. | -| `docs/getting-started/_quickstart-parts/_quickstart_{nodejs,python,python_sync,golang,java,dotnet,ruby}.mdx` | "The tenant passed in needs to be either the **tenant id** or the **tenant key**." | "tenant key" | Whether `permit.check()` accepts tenant IDs could not be verified. | -| `docs/getting-started/slack-support.mdx` | "/permit-escalate - Pro/Enterprise Support Only" and "Works in private channels and DMs, not in public channels" | Kept, partly verified. | The plan restriction matches the pricing page's "Dedicated Slack Channel" row, but the public-channel restriction could not be verified. | -| `docs/how-to/build-policies/abac/building-abac-policy.mdx` | "Tenant boundaries are not automatically enforced for user sets" | Kept and expanded with its consequence. | The behavior was never verified in source. Confirm it. | -| `docs/how-to/build-policies/abac/defining-attributes.mdx` | The role attribute item labeled **Role Attributes (EAP)** | Used verbatim from the settings panel screenshot. | Confirm whether role attributes are still early access, and whether the page should say so. | -| `docs/how-to/build-policies/abac/patterns.mdx` | Nothing (this pattern is new) | "Ownership via list on user profile" builds a user set with `user.owned_files` `array contains (ref)` `resource.id`. | The operator and the `{"ref": ...}` operand form are both documented, and `input.resource.attributes` is part of the PDP query, but a user set condition that references a resource attribute was never observed in the product. Confirm the condition works, or the pattern goes. | -| `docs/how-to/build-policies/abac/patterns.mdx` | The `permit.custom` Rego sample | Kept as published. | It uses Rego v0 partial-rule syntax with a `default` on a partial object rule, which may not parse on the PDP's OPA version. It needs a check against the PDP's OPA. | -| `docs/how-to/build-policies/abac/patterns.mdx` | "ReBAC is a subset of ABAC" | Removed. | An unverified generalization. Decide whether the conceptual claim belongs in the docs. | -| `docs/how-to/build-policies/abac/time-based-role.mdx` | Samples using `george@test.com` | Kept byte-identical. | Not a style-guide address. The change touches code samples. | -| `docs/how-to/build-policies/policy-basics.mdx` | "The **Default Permissions** panel holds those defaults. A new environment starts with these values:" | "The panel in the screenshot below holds these values:" | The defaults are per-environment and editable, and the state of a brand-new environment is documented nowhere. Confirm the shipped defaults. | -| `docs/how-to/build-policies/policy-basics.mdx` | "Select a tenant, or select **All Tenants** to drop the filter." | "Select a tenant." | No All Tenants option appears in the current Directory screen. Put it back if the option still exists. | -| `docs/how-to/build-policies/policy-basics.mdx` | "Permissions ... can also be assigned directly to individual users or entities" | Removed. | Direct user permissions could not be verified in Permit's RBAC model. | -| `docs/how-to/build-policies/rbac/components.mdx` | "Top level represents the fact that Roles have higher priority in policy evaluation than Instance-level Roles." | Top level is defined as tenant-wide. | No evidence of role priority exists in the docs or the API. Confirm whether priority exists. | -| `docs/how-to/build-policies/rebac/building-rebac-policies.mdx`, `docs/overview/create-a-rebac-policy.mdx` | "Once you successfully define the relationships on the roles - it will automatically create the roles for you in the policy editor." | Removed from both pages. | What Permit auto-creates when you define a relation could not be verified. | -| `docs/how-to/deploy/cloud-hosts/aws-ecs-fargate.mdx` | "Start with 1 vCPU" | Kept, unverified. | The example task definition in the deployments repository uses 512 CPU units and 1024 MiB. Confirm the recommendation. | -| `docs/how-to/deploy/cloud-hosts/gcp-cloud-run.mdx` | "`watchdog: error` is expected in Cloud Run due to how Cloud Run handles background processes" | Replaced with the verified Horizon behavior, which reports `ok` when the direct check succeeds. | The cause could not be verified. Confirm it to restore the explanation. | -| `docs/how-to/deploy/cloud-hosts/terraform.mdx`, `docs/how-to/deploy/cloud-hosts/pulumi.mdx` | That the example repository's `main.tf` and `__main__.py` install the chart as published | The pages tell the reader to change the repository URL. | Both install chart 0.0.2 from `https://permitio.github.io/sidecar`, which returns 404, while the chart is served from `https://permitio.github.io/PDP`. Fix `permit-pdp-deployments-examples`. | -| `docs/how-to/deploy/cloud-hosts/terraform.mdx` | The example's Helm provider 2.x `set {}` and `kubernetes {}` blocks with no version pin | The page notes the breaking change. | Helm provider 3.0.0 changed both blocks. Pin the provider in the example repository. | -| `docs/how-to/deploy/deploy-to-production.mdx` | "multiply the number of policy objects ... by 6 KB ... 100,000 users, 500,000 resource instances, and 100 tenants needs about 3.5 GB" | Kept, unverified. | Operational sizing guidance with no source and no replacement. Remove it if you cannot confirm it. | -| `docs/how-to/deploy/deploy-to-production.mdx` | "CPU: about 200 millicores ... limit of at least 1000 millicores; Memory: about 512 MiB" | Kept, unverified. | Not in source. The Helm chart defaults (256m CPU request, 512Mi memory request, 1Gi memory limit) are close but not identical. | -| `docs/how-to/deploy/on-prem/change-organization-tier.mdx` | The before and after UI strings, a "PRO" badge and "14 days left in Pro Trial" | Removed. | Frontend strings could not be verified. A screenshot settles them. | -| `docs/how-to/deploy/on-prem/change-organization-tier.mdx` | "`billing_tier` controls ... Upgrade prompts" | Removed. | Could not verify. | -| `docs/how-to/deploy/on-prem/installation.mdx`, `docs/how-to/deploy/on-prem/quick-start.mdx` | "(no flags) Deploy to production Kubernetes (EKS, GKE, AKS)" and the targets-table row "None: Deploys to the cluster in your current kubectl context" | Both pages document `--gke` for any existing cluster and warn readers to add it. | `install-permit-platform.sh` runs `kind create cluster` with no target flag, and only `--gke` sets `ENVIRONMENT=production`, so a no-flag run on EKS or AKS fails although `--help` promises production. Fix the script so no flag means production, or accept the doc change. | -| `docs/how-to/deploy/on-prem/installation.mdx`, `docs/how-to/deploy/on-prem/quick-start.mdx` | That a Kind install works with the package's empty `imageRegistry` | Both pages say the registry check applies to every target except OpenShift. | `configure_image_registry()` exits on an empty `global.imageRegistry` for Kind too, while the package ships `imageRegistry: ""` and the internal Kind test sets only `frontendDomain`. Confirm what Kind users set. | -| `docs/how-to/deploy/on-prem/installation.mdx` | The `--gke` flag | Kept, with a note that `--help` omits it. | The parser accepts `--gke` but `show_help` does not list it. Add it to `show_help` in `permitio/permit-deployments`. | -| `docs/how-to/deploy/on-prem/installation.mdx` | "35 services total", "Deployments (35 total)", "Infrastructure Services (10 services)" listing 11, "Services (26 total)", "Found 35 images", "Loaded 12 platform images", "~35 images" | All counts removed. The page lists services by group and tells readers to run `kubectl get deployments,services,pvc`. | The counts contradicted each other and the internal README, which lists 18 Permit images, 6 third-party images and 33 healthy pods. Code comments on `management.mdx`, `troubleshooting.mdx` and `reference.mdx` still say "all 35 Permit services". Supply one count. | -| `docs/how-to/deploy/on-prem/installation.mdx` | "PostgreSQL ... Storage: 20GB persistent volume", `postgres-pvc ... 10Gi`, "OpenSearch 15GB (3 shards default)", "Redis 5GB" | Sizes removed. The page points at `thirdPartyServices..persistence.size`. | Published sizes deleted because they contradicted each other and the package values (postgres 40Gi, redis 15Gi, opensearch 20Gi, rabbitmq 5Gi, keycloak 5Gi). Confirm the shipped sizes. | -| `docs/how-to/deploy/on-prem/installation.mdx`, `docs/how-to/deploy/on-prem/quick-start.mdx`, `docs/how-to/deploy/on-prem/landing.mdx` | Step timings "(1-2 minutes)", "(3-5 minutes)", "8-15 minutes", "5-10 minutes", "10-15 minutes", "just a few minutes", push "10-20 minutes", "~12GB upload" | All removed. | The figures contradicted each other and the internal README's package size, with no source for any of them. Supply measured timings. | -| `docs/how-to/deploy/on-prem/landing.mdx` | "High availability - Multiple replicas for critical services" | Removed. | Replica counts could not be verified in the chart. Confirm them. | -| `docs/how-to/deploy/on-prem/management.mdx` | "Or register a new account" in the sign-in block | Kept inside the code block only. | Whether self-registration is enabled in the installed Keycloak realm is not verifiable from the installer or the chart. | -| `docs/how-to/deploy/on-prem/management.mdx` | The health URLs `/health`, `/scim/health`, `/api/v2/health` and backend `:8000/health` | Kept as in the original. | None was verified against the services' routes. | -| `docs/how-to/deploy/on-prem/prerequisites.mdx` | The storage table with growth rates and "Total Production Storage: 51GB minimum" | Removed. The page points at `values.yaml`. | The sizes are stale against the package values and the growth rates are unverifiable. Publish current figures. | -| `docs/how-to/deploy/on-prem/prerequisites.mdx` | "Small teams (50-500 users)" and "Large organizations (1000+ users)" sizing | Removed. | No source. Supply sizing guidance. | -| `docs/how-to/deploy/on-prem/prerequisites.mdx` | "Compatible with both GKE Standard and Autopilot" | Removed. | Could not verify, and the installer runs database containers as root, which Autopilot may restrict. | -| `docs/how-to/deploy/on-prem/prerequisites.mdx` | "Version: OpenShift 4.10+ on AWS" against "OCP 4.8+" and "Red Hat OpenShift: 4.8+" | Kept 4.8, which appeared three times. | The installer checks no version minimum, so the supported floor remains unverified. Confirm it. | -| `docs/how-to/deploy/on-prem/prerequisites.mdx` | The rationale for giving the deploy key write access | Write access kept, without the reason. | Why Policy Sync needs write access was not traced in source. | -| `docs/how-to/deploy/on-prem/reference.mdx` | Storage sizes "10Gi Minimum, 20Gi+ for production" and "15Gi Minimum for 3 shards", and the image tags `opal-server 0.7.5-rc.7`, `keycloak 20.0.5`, `opensearch 2.11.0`, `postgres_15-alpine`, `rabbitmq_3.12.10` | Kept inside code blocks as examples, with the prose naming the package's `values.yaml` as the source of truth. | The chart's `values.yaml` is not in `permitio/permit-deployments`, so no default can be verified. Publish it and the page can state real defaults. | -| `docs/how-to/deploy/overview.mdx` | "Custom Hosted PDP deployments ... are available to enterprise tier customers" | The contact route kept, the tier dropped. | The plan-tier claim could not be verified. | -| `docs/how-to/enforce-permissions/all-tenants-check.mdx` | "The tenant key isn't required and will be ignored if provided" | Kept, unverified. | Never verified in the policy source. | -| `docs/how-to/enforce-permissions/all-tenants-check.mdx` | "Currently, using relationship-based access control (ReBAC) doesn't work for the All Tenants Check" | Kept as a limitation, without "currently". | The behavior was never verified in the policy source. | -| `docs/how-to/enforce-permissions/authorized-users.mdx` | "That feature is performance-intensive and is disabled by default" | Default-off verified, the performance claim kept. | The performance cost was never measured. Confirm it or drop the clause. | -| `docs/how-to/enforce-permissions/data-filtering.mdx` | "Simplified Partial-evaluation, is an upcoming feature in advanced stages of release, which includes built-in translation to SQL" | Removed. | Availability could not be verified. Confirm whether built-in SQL translation ships. | -| `docs/how-to/enforce-permissions/data-filtering.mdx` | "This capability exists in Open Policy Agent (OPA) under the compile API and is already available within Permit's PDP" | Reworded to the OPA Compile API through the PDP container's exposed OPA port. | Whether Permit's generated policies partially evaluate cleanly was never verified. | -| `docs/how-to/enforce-permissions/url-mapping/configuring-jwks.mdx` | "In order to start using URL Mapping with Permit, you need to add your obtained JWKs ... sending API calls directly from the frontend" (abridged) | The page names Permit Elements frontend login as the verified use of the environment JWKS. | The spec describes the environment `jwks` field as "jwks for element frontend only login". Confirm whether URL mapping checks use it. | -| `docs/how-to/enforce-permissions/url-mapping/regex-url-mapping-check.mdx` | "This feature is currently only available through the Permit.io API & PDP API" | The page tells readers to create regex rules with the API, without claiming the dashboard lacks them. | Whether the URL Mapping dashboard supports regex rules could not be verified. | -| `docs/how-to/enforce-permissions/url-mapping/regex-url-mapping-check.mdx` | "The `secret` value is still required for now, even though it isn't used. This will be fixed in a future release of the proxy_configs API." | Kept only the verified facts: the spec lists `secret` as required and the PDP's `/allowed_url` code never reads it. | The API still requires a field nothing reads. Fix `proxy_configs` or the page keeps explaining the dead field. | -| `docs/how-to/enforce-permissions/url-mapping/url-mapping-check.mdx` | "Each rule sets the HTTP method, the URL template, the resource, and the action" as a description of the UI | Kept. | Based on the `MappingRule` schema and the existing screenshot; the dashboard field labels were never verified. | -| `docs/how-to/manage-data/loading-data.mdx` | "There are no practical limits on number of objects or object sizes." | Removed. | Could not verify. Supply the real limits. | -| `docs/how-to/manage-data/loading-data.mdx` | "There are limits on the overall data volume that can be loaded to a single PDP, which can be bypassed via PDP Sharding" | Restated as a pointer to Sharded Edge PDPs for very large data sets. | No stated limit was found anywhere. Supply one. | -| `docs/how-to/manage-data/local-facts-uploader.mdx` | "Faster Sync Times: Despite increased request latency, data updates are typically received faster compared to data updates via the Permit API" | Removed. | Could not verify. | -| `docs/how-to/manage-data/local-facts-uploader.mdx` | "CPU Usage: PDP CPU usage may increase with high traffic to proxy facts endpoints" | Removed. | Could not verify. | -| `docs/how-to/manage-data/local-facts-uploader.mdx` | The PDP version floor 0.5.1 for the wait timeout | Kept. | The wait-timeout dependency already exists in tag 0.5.0, so 0.5.1 is safe but possibly conservative. Confirm the floor. | -| `docs/how-to/manage-data/use-external-data-source.mdx` | "Custom scopes are supported from PDP v0.2.15" | Removed. | `permitio/PDP` tags start at 0.3.0, so the version could not be checked. Confirm the introducing release. | -| `docs/how-to/monitoring-pdps/monitoring-pdps.mdx` | "Read timeouts during consistent update requests / HTTP 500 during sync operations ... do not indicate disconnects" and "most red PDPs in production are stopped PDPs" | Kept. | Support guidance that is not verifiable from PDP source. Confirm it. | -| `docs/how-to/monitoring-pdps/monitoring-pdps.mdx` | The navigation path (organization sidebar > Monitoring > Pdps tab) and the filters | Kept, taken from the existing screenshot only. | This is an early access UI. A current screenshot settles the navigation. | -| `docs/how-to/ownership.mdx` | "Go to the ABAC Rules tab, and enable ABAC Options." | Removed. | No enable toggle could be verified. Confirm whether one exists. | -| `docs/how-to/permit-cli/permit-cli-envs.mdx` | env create "--env-key will be derived from name if not provided" and the custom branch "default is set to the environment ID" | Removed. | Neither default could be verified in `permit-cli` source. Confirm them. | -| `docs/how-to/permit-cli/permit-cli-pdp.mdx` | "display the container ID and name" | Removed. | The source prints "The PDP is running on port 7766" instead. Confirm the intended output. | -| `docs/how-to/policy-guard/policy_guard.mdx` | "Only a workspace Owner can add or remove new guarding policy rules." | "an organization API key or Workspace Owner", from the backend's org-admin check. | The mapping of `MemberAccessLevel.ADMIN` on ORG to the UI label "Workspace Owner" is inferred, not verified in the frontend. | -| `docs/how-to/policy-guard/policy_guard.mdx` | Nothing (this claim is new) | "In a guarded environment, a change to a permission that a Policy Guard rule covers fails with a 403 Forbidden error" | The 403 is verified for the check path, but the exact set of guarded object edits was not exhaustively verified. | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | "This feature is currently available to whitelisted organizations only!" and the offer to "add you to our VIP whitelist" | Removed. | The endpoint is public in the OpenAPI spec and the restriction appears in no source. Confirm availability. | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | "Maximum replay duration: 30 days" | Removed. | Not in `AuditLogReplayRequest`. Confirm the bound. | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | "Maximum concurrency: 10 (contact support for higher limits)" | Kept, with a warning that the spec contradicts itself. | `concurrency_limit` has `"default": 10` and a description saying "max: 5". Fix the spec and the page can state one number. | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | "Maximum timeout for a session is 60 seconds" | Removed. | The spec has only `graceful_shutdown_s`, "Graceful shutdown time in seconds", default 60. Confirm whether a session timeout exists. | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | "Replay requests may be throttled based on your plan" | Removed. | Could not verify. | -| `docs/how-to/use-audit-logs/audit-log-replay.mdx` | "Certain audit log types may not be replayable (Authorized-users, Bulk check, etc.)" | Removed. | Could not verify. | -| `docs/how-to/use-audit-logs/types-and-filtering.mdx` | "Max number of results for this api is 10,000" | Replaced with the spec's page size of 100. | The ceiling could not be verified. Confirm it. | -| `docs/how-to/use-audit-logs/types-and-filtering.mdx` | "Permit deletes old audit logs periodically." | Permit stores audit logs for a limited time, a check from far in the past can be missing, and readers should contact Permit about retention. | Neither the schedule nor the retention period could be verified, and `docs/permit-mcp-gateway/audit-logs.mdx` still carries the old sentence and points here for the details. | -| `docs/integrations/database-access-control/trino-integration.mdx` | "If Trino cannot reach the PDP or the PDP errors, Trino denies the query." | Narrowed to the PDP side, where `checks.rs` returns false on an OPA error. | Trino's behavior when the PDP is unreachable was never verified. | -| `docs/integrations/database-access-control/trino-integration.mdx` | "Procedure ... Resource Name: `trino_procedure___`" | The mapping table now shows the PDP's `trino_function___`. | `permit-cli`'s `trinoUtils.ts` still creates `trino_procedure_*`, `trino_view_*` and `trino_materialized_view_*` resources that the PDP never checks, since views are sent as table resources. Fix `permit-cli`. | -| `docs/integrations/feature-flagging/casl.mdx` | "the `permit-fe-sdk` fully supports version 6 of CASL" | Removed. | `permit-fe-sdk` has no CASL dependency and its README links the CASL v5 docs. Confirm the supported version. | -| `docs/integrations/gateways/kong.mdx` | The documented Kong flow, "configure the Kong OPA plugin to call the PDP at /kong" | The steps stay with a danger admonition, and a reverse proxy holds the API key. | `/kong` is gated by `enforce_pdp_token` and the Kong OPA plugin has no header field, so no PDP version accepts the plugin's request. A PDP-side option, such as a Kong-specific token or a Permit-published Kong plugin, would remove the extra hop and the API key in a proxy config. A stale comment in `horizon/config.py` still calls the endpoint unauthenticated. | -| `docs/integrations/gateways/kong.mdx` | "continue to make decisions extremely quickly, on the order of 1-5 ms" | Removed. | Not among the owner-confirmed performance figures. | -| `docs/integrations/gateways/nginx.mdx` | The implied claim that the `auth_request` setup blocks requests the policy denies | The steps stay with a danger admonition, plus the `/allowed` contract for an njs or Lua handler. | `/nginx_allowed` is declared `status_code=200` and returns `{"allow": false}` with HTTP 200, while `auth_request` denies only on 401 or 403, so plain NGINX cannot block. Add a status-code mode to the PDP and the page can offer a copy-paste config. | -| `docs/integrations/gitops/custom_policy.mdx`, `docs/integrations/gitops/github.mdx` | "avoid editing policy code outside of this folder, as it could potentially be overridden by our code" | Kept as a warning, with an instruction to check `root.rego` after dashboard changes. | Whether Policy Sync regenerates the top-level `root.rego` was never verified; the backend whitelists only paths containing "custom", "rebac" and "user_permissions" when resolving conflicts. | -| `docs/integrations/gitops/custom_policy.mdx` | The repository layout table | Published from `permitio/generated-policy-example`. | The layout of current generated repositories may differ. Confirm it. | -| `docs/integrations/gitops/github.mdx` | "your private key will be securely stored on our end, and no passphrase will be required" | Replaced with the spec fact that `SSHAuthData` has no passphrase field. | The storage-security claim was unverifiable. Confirm how the key is stored. | -| `docs/integrations/gitops/overview.mdx` | "The feature is available **in trial** to all Permit users as a self-service" | A link to the pricing page, with no plan claim. | Stale plan wording. Decide whether the docs state plan availability at all. | -| `docs/integrations/infra-as-code/terraform-provider.mdx` | "Ensure you're using an environment-level API key, not a workspace-level key; Verify the API key has the correct permissions" | Kept in the troubleshooting table as "use the API key of the environment you manage". | Never verified against provider behavior. | -| `docs/integrations/permit-mcp/overview.mdx` | The demo's four seeded sign-ins | Kept, with a warning to replace the fixed passwords before running the app anywhere but the reader's machine. | `init_db()` creates them. Decide whether published demo credentials stay. | -| `docs/integrations/permit-mcp/overview.mdx`, `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | The pinned models `gemini-2.0-flash` and `gemini-2.5-flash-preview-04-17` | Code unchanged, with a note to switch to a current model on a model-not-found error. | `gemini-2.0-flash` shut down on June 1 2026 per Google's deprecations page, and the same pins sit in `permitio/permit-mcp`. Update the repository. | -| `docs/integrations/policy-engines/overview.mdx` | The implied claim that the Permit PDP image runs Cedar | The page says the Permit PDP runs OPA and the OPAL client can run cedar-agent. | `permitio/PDP` main has no Cedar references, while `faq.mdx`, `overview/glossary.mdx`, `overview/how-does-it-work.mdx`, `how-to/build-policies/policy-basics.mdx` and `concepts/pdp/configuration.mdx` still say Permit supports Cedar, and `gitops/custom_policy.mdx` no longer claims custom Cedar code. Settle Cedar once for all of them. | -| `docs/integrations/workflow-automation/n8n.mdx` | "use a local PDP container for better performance and advanced policy support" | Kept only the ABAC requirement. | The performance claim was never measured. | -| `docs/manage-your-account/permit-logs.mdx` | "Only workspace owners may view activity logs / the API log." | Kept, unverified. | It could not be verified in source, and the same sentence was removed from `docs/api/api-with-cli.mdx`. Confirm it and both pages can agree. | -| `docs/manage-your-account/workspace-settings.mdx` | "Enterprise plan customers and Pro plan customers (for an additional fee) can request a tailored DPA from Permit support or their customer success manager" | Pointers to the pricing page and to Permit support. | The plan and fee facts are volatile and were verified only against a pricing page row. Decide whether the docs state them. | -| `docs/manage-your-account/workspace-settings.mdx` | "their access level will be `Mixed`, if its more than two projects with different access" | "when those roles differ in access level" | The "more than two projects" threshold could not be verified; the screenshot shows `Mixed` for a member with two projects. | -| `docs/manage-your-account/workspace-settings.mdx` | "if you must work with PII you can keep it solely on your self-hosted PDPs" | Removed. Kept that the user key is the only required user field. | No supported mechanism for keeping PII only on self-hosted PDPs could be found. Confirm whether one exists. | -| `docs/manage-your-account/workspace-settings.mdx` | "click **Give access to entire workspace** to assign a Workspace Owner, Workspace Editor, or Workspace Viewer role" | The step says to select the workspace access level, without enumerating. | The invitation dialog in the page's own video offers only Owner and Editor, while the API enum has three levels. Confirm what the dialog offers. | -| `docs/modeling/food-delivery-system-example-using-nuxt.mdx` | "To deliver an order: User must have the rider role (RBAC), Order must be assigned to them (ReBAC), For free delivery orders, a rider must have 500+ rides (ABAC)" as an AND of all three | The rules and checks are described without AND semantics, and the negative test steps are removed. | Permit combines role, instance role and condition set grants with OR, so the intended policy cannot be reconstructed from the repository. State the intended policy. | -| `docs/modeling/food-delivery-system-example-using-nuxt.mdx` | The endpoint table's RBAC rows for `GET /meals` and `GET /orders` | The table says None, with a warning to remove the early return before reusing the middleware. | `check-role.ts` returns before `permit.check()` for every `GET`, so those endpoints have no permission check at all. Fix `permitio/permit-nuxt-example`. | -| `docs/modeling/google-drive.mdx` | "Permit will assume such instance exists on your end and create it implicitly" | "Permit creates the resource instance" | Never re-verified against backend source. | -| `docs/modeling/mesa-verde.mdx` | "we use events from the authentication provider (Stytch) to call the Permit's role assignment and create tenant APIs" | Kept, reworded. | `syncUser` runs on first login, but the exact Stytch event was never verified. | -| `docs/modeling/mesa-verde.mdx` | "In our application, we are allowing Account Member users to request the Account Beneficiary role" | Kept. | `setup.js` leaves `roles_to_levels` empty for the access request element, so the requested role comes from dashboard configuration that was never verified. | -| `docs/modeling/mesa-verde.mdx` | "the Permit policy as code engine generates it in Policy Languages such as Rego or Cedar and pushes it to a Git repository" | Reworded to link GitOps. | Neither Cedar generation nor an automatic push without GitOps configured could be verified. | -| `docs/modeling/rebac-GHC.mdx` | The hosted demo at `https://ghc.up.railway.app/` with four accounts sharing the password `Aa123456!` | The whole section is removed and the page points at the repository to run locally. The `#hosted-app` anchor is dropped and has no inbound link. | Published shared credentials. Decide whether a hosted demo returns, and with what accounts. | -| `docs/modeling/rebac-GHC.mdx` | The GHC plan page's `view` check on `alt_medicine_pg` | The page notes that the card stays hidden. | `scripts/setupPermit.js` never creates that resource. Fix the seed script. | -| `docs/overview/best-practices.mdx` | "run Permit checks in read-only mode" | Reworded to calling `permit.check()` next to the existing check and logging both. | No read-only mode exists in any SDK or doc. Confirm whether one is planned. | -| `docs/overview/create-a-rebac-policy.mdx` | The dashboard control labels for creating a role derivation | The step states the two derivations in a table and links to the ReBAC page for the dashboard steps. | The Policy Editor field labels could not be verified from source or from another docs page. A current screenshot settles them. | -| `docs/overview/create-a-rebac-policy.mdx` | "A resource cannot be its own parent. If a resource requires a self-relation, consider using an alternative relation type such as owner or container." | Removed. | Could not verify. Confirm whether self-relations are rejected. | -| `docs/overview/glossary.mdx` | "Checking permissions for the same user key in several environments in the same month counts as one MAU." and "MAU is the count of unique user keys ... across your workspace (organization)" | Removed. | The billing counting rule could not be verified; `workspace-usage.mdx` says only unique users per month. Confirm the rule. | -| `docs/overview/glossary.mdx` | "though most teams need only one" (workspaces) | Removed. | Could not verify. | -| `docs/overview/glossary.mdx` | "It is recursive, and a critical part of a secure access control system. It includes features such as meta roles, meta audit logs, and API logs." | Replaced with a member roles link. | The feature names could not be verified. | -| `docs/overview/perform-policy-check-with-cloud-pdp.mdx` | "It is **fully managed and eventually consistent**. Use it to try Permit and for production workloads that don't require strict read-your-own-writes guarantees." | Removed. | The Cloud PDP consistency model is stated in no doc or source, including `cloud-pdp-capabilities.mdx`. Publish it. | -| `docs/overview/sync-your-first-user-with-sdk.mdx` | "Permit is API-first: everything you can do in the UI, you can also do with the API" | "Everything you did with the API in this walkthrough, you can also do in the Permit dashboard" | The absolute claim is not verifiable. Confirm it to restore the stronger wording. | -| `docs/permit-mcp-gateway/advanced-features.mdx` | "Sub-millisecond authorization decisions" for the gateway | Removed. | Not owner-confirmed for the gateway; the confirmed sub-millisecond figure is for the PDP, and the marketing enterprise page says "High-performance PDP, sub-10ms". | -| `docs/permit-mcp-gateway/advanced-features.mdx` | "Anomaly detection ... under development as part of session monitoring" and "Shadow agent detection ... an area of active research" | Both removed with the internal admonition that listed them. | Roadmap items that could not be verified. Decide whether they ship and belong in the docs. | -| `docs/permit-mcp-gateway/advanced-features.mdx` | "Agent Interrogation is under active development ... being refined", and the maturity notes "early access", "active development", "emerging" and "roadmap" for Agent Verification, Session Monitoring and Intent-Based Access Control | Replaced with "Contact Permit" in the availability table, with the `#feature-maturity-summary` anchor kept. | Availability could not be verified for any of the four. | -| `docs/permit-mcp-gateway/advanced-features.mdx` | Enterprise-plan status of Agent Interrogation, Agent Verification, Session Monitoring, Permission Receipts and Intent-Based Access Control | Removed. | The pricing page lists only HITL approvals and configurable consent windows as Enterprise. Confirm the plan for the other five. | -| `docs/permit-mcp-gateway/advanced-features.mdx` | The three parts of the composite identity, drift-triggered reactions (downgrade trust, re-consent, block, approval), step-up consent, declared-intent logging, drift history, per-workflow policy, exportable permission receipts and the session monitoring intent comparison | Kept, unverified. | The gateway source search hit the GitHub rate limit, and only `identify_self`, fingerprinting and drift monitoring are confirmed. Confirm these ship. | -| `docs/permit-mcp-gateway/architecture.mdx` | The rate-limit table: `/api/auth/sign-in` 100 req / 5 min, `/api/auth/sign-up` 100 req / 10 min, `/oauth/register` 100 req/min, `/mcp` 1000 req/min, writes 1200 req/min, all traffic 2000 req/min | Kept only the per-IP behavior, the 429 JSON body and the NAT note. | Production limits are enforced by AWS WAF at the edge, which is not in the repository. Publish the real values to restore the table. | -| `docs/permit-mcp-gateway/architecture.mdx` | The Data Flow diagram and protocol table with ports 8001, 8002, 3000, 8080, 6379, 5432 and "AWS ALB (TLS termination)" | Replaced with a port-free table of what moves. | Hosted-infrastructure internals deleted as volatile and not actionable. Decide whether operators need them. | -| `docs/permit-mcp-gateway/architecture.mdx` | The env var table entries `GATEWAY_JWT_TTL_SECONDS` (default 300, range 60-3600) and `GATEWAY_JWT_REQUIRE_VAULT` | Removed, with the 5-minute default kept. | Both are verified in `gateway/src/config.rs` but are not settable on the hosted gateway, and the on-prem chart exposes the vault flag under a different key. Decide what to publish. | -| `docs/permit-mcp-gateway/architecture.mdx` | "When the token vault is enabled (`VAULT_ENABLED=true` + `AWS_KMS_KEY_ID`), the key is encrypted at rest using AES-256-GCM with AWS KMS envelope encryption; without vault it is stored as plaintext JSON" | Removed. | The on-prem chart does not wire the KMS vault. Decide whether the storage detail should be published. | -| `docs/permit-mcp-gateway/architecture.mdx` | The rotation procedure `redis-cli DEL gateway:jwt:signing_key` then `kubectl rollout restart deployment/gateway` | The page says to contact your Permit team. The 90-day warning, the metric name and the kid behavior stay. | The deployment name is wrong for the on-prem chart (`agent-security-gateway`) and the steps are not actionable for hosted customers. Supply a real procedure. | -| `docs/permit-mcp-gateway/architecture.mdx` | Whether the admin dashboard runs in the customer network in the customer-controlled model | The table says "Contact Permit for your deployment". | Could not verify. | -| `docs/permit-mcp-gateway/audit-logs.mdx` | The denial reasons "User not found" and "Resource not found" | Replaced with the Permit denial codes `user_not_synced` and `no_such_resource`. | Those exact strings appear in no source; the platform only rewrites the no-role case. Confirm the messages the screen shows. | -| `docs/permit-mcp-gateway/audit-logs.mdx` | "Export or review the entries" for compliance reports | Replaced with the List audit logs API. | No export feature could be verified on the Audit Log screen. Confirm whether one exists. | -| `docs/permit-mcp-gateway/audit-logs.mdx` | "The Permit dashboard shows the full policy evaluation chain, including which derived roles were checked" | Narrowed to the decision log's check and reason. | The derived-role detail could not be verified. | -| `docs/permit-mcp-gateway/authentication-methods.mdx` | "Passkeys require an initial registration via another method (email/password or social login)" | Reworded to the consequence: a user without a registered passkey cannot sign in with one, so keep another method on. | The consent service has a passkey sign-in button but no registration UI was found. Confirm how a passkey is registered. | -| `docs/permit-mcp-gateway/authentication-methods.mdx` | The Okta, Entra ID and Google Workspace console click paths | Kept, unverified, with a note that console labels change. | Third-party UIs that nobody could check. Decide whether the docs carry them. | -| `docs/permit-mcp-gateway/consent-service.mdx` | "Soft TTL (inactivity) 30 days: if no tool calls are made for 30 days, the session is removed" and "Hard TTL (absolute) 90 days: maximum session lifetime regardless of activity" | "Redis removes the application session 90 days after the last tool call." | The soft TTL's cleanup job is marked not implemented, and `touch_session` re-sets the 90-day expiry on every request, so the hard TTL is not absolute. `guide.mdx`, `advanced-features.mdx` and `overview.mdx` still state the old two rules, and the OAuth provider's 30-day refresh token may be an effective limit. Confirm the product behavior. | -| `docs/permit-mcp-gateway/consent-service.mdx`, `docs/permit-mcp-gateway/platform.mdx`, `docs/permit-mcp-gateway/managing-humans-and-agents.mdx` | "Revoking access terminates any active sessions for that user on the affected MCP server" and "immediately invalidates the session" | All three pages say only that the agents' next tool call to that server is denied. | Session deletion on revocation could not be verified. Confirm whether sessions end too. | -| `docs/permit-mcp-gateway/consent-service.mdx` | Per-tool trust levels at consent | The page says per-tool edits happen only for a server added through Dynamic MCPs, up to the max trust level. | The n8n demo shows per-tool trust for an admin-imported server, which the source does not support. Confirm which case that demo and its `tool-import.png` show. | -| `docs/permit-mcp-gateway/demos/n8n-linear-mcp-gateway.mdx` | "you will be asked to import and assign trust levels for all of Linear's tools" and "go to the Permit MCP Gateway dashboard and toggle the trust level" | Reworded to one trust level granted to the workflow, with links to the Consent Service and the Agents page. | Both claims rest on screenshots nobody could match to a current screen. Confirm the screens the demo shows. | -| `docs/permit-mcp-gateway/enterprise-deployment.mdx` | "Audit logs: Your infrastructure + Permit.io (configurable)" and "Policies and users can be migrated between deployment models" for customer-controlled | Kept, unverified. | Both carry over from the original page with no source. Confirm them. | -| `docs/permit-mcp-gateway/enterprise-deployment.mdx` | "Resilience: authorization continues even if internet connectivity to Permit.io is temporarily interrupted" | Reworded to the mechanism: the PDP keeps its last synced policy. | The behavior is that of OPAL-backed PDPs and was never measured for the gateway. | -| `docs/permit-mcp-gateway/host-setup.mdx` | The rollout phase durations "1-2 weeks" and "2-4 weeks" | Kept, labeled as suggestions. | Guidance rather than product fact. Confirm them or drop them. | -| `docs/permit-mcp-gateway/http-egress-proxy/cli.mdx`, `docs/permit-mcp-gateway/http-egress-proxy/security.mdx` | Agent identity and the intent guardian are enabled by emailing support | Kept, unchanged. | `egress-rules.mdx` was corrected to the real per-host `guardian_enabled` and `agent_identity_required` toggles plus the fleet-wide `ENABLE_PROXY_INTENT_CONTROLS`, so the three pages now contradict each other. Confirm whether the email step is real. | -| `docs/permit-mcp-gateway/human-in-the-loop.mdx` | The keyboard shortcuts, card border colors, "Extend +5 min" in the last 60 seconds and the preset rejection reasons | Kept, unverified. | The gateway source search hit the GitHub rate limit, and these are volatile UI facts. | -| `docs/permit-mcp-gateway/index.mdx` | "A Permit.io account (free tier available)" | Removed. | The plan-tier claim could not be verified in the docs. | -| `docs/permit-mcp-gateway/managing-humans-and-agents.mdx` | "The same person using multiple MCP clients creates separate agent identities", against the page's own example where one Cursor identity holds roles on two humans' profiles | "If the same agent identity is authorized by two humans, it holds a role on each profile." | Each client gets a `client_id` through dynamic client registration and sessions are keyed by client_id plus subject, but no page says whether two humans' Cursor installs share a client_id. Confirm it. | -| `docs/permit-mcp-gateway/overview.mdx` | "Hosted (SaaS) ... Available on all plans" and "The hosted deployment is available for all plans" | Removed. | The plan-tier claim could not be verified. | -| `docs/permit-mcp-gateway/permit-integration.mdx` | "RBAC, ABAC, and ReBAC policy models", "Real-time policy updates via OPAL", "Policy-as-code via Terraform provider" and "Local PDP option ... decisions stay within your network" | Replaced with the Cloud PDP default, a link to the Local PDP section, next-call policy changes, the audit log and the Permit API. | `gateway/src/config.rs` defaults `PERMIT_PDP_URL` to the Cloud PDP, which does not evaluate ABAC. Confirm which policy models the gateway supports. | -| `docs/permit-mcp-gateway/permit-integration.mdx` | "The environment name typically matches the host name" | Replaced with reading the linked project and environment on the host. | Could not verify. | -| `docs/permit-mcp-gateway/permit-integration.mdx` | "Allowing the same MCP server resource to be shared across tenants if needed" | Removed. | Could not verify. The `default` tenant is verified for static and dynamic resources. | -| `docs/permit-mcp-gateway/permit-integration.mdx` | The effective-permission rows where the profile relation sits above the agent role, for example `{server}-medium` plus a `high` relation giving medium | Kept, unverified. | The nine derived-role rules have no rule for `{server}-medium` + `high`, `{server}-low` + `medium` or `{server}-low` + `high`, and each grant writes a single relation tuple. Confirm how those combinations derive a role, or fix the product. | -| `docs/quick-start/aspnet.mdx` | The page title "ASP.NET Application" | ".NET app", because the sample is an `HttpListener` console app. | The sidebar label in `sidebars.js` still says "ASP.NET". Align it or revert the title. | -| `docs/quick-start/nextjs.mdx` | The middleware sample that imports the `permitio` SDK | Kept, unverified. | Whether the SDK runs in Next.js middleware's default Edge runtime could not be verified. One deploy settles it. | -| `docs/sdk/cpp/quickstart-cpp.mdx`, `docs/sdk/erlang/quickstart-erlang.mdx`, `docs/sdk/kotlin/quickstart-kotlin.mdx`, `docs/sdk/php/quickstart-php.mdx` | "Currently, the SDK is in beta." | Removed. | No README states beta status, and the C++, Kotlin and Erlang repositories were last pushed on 2025-01-09. The sidebar labels in `sidebars.js` still say "(Beta)". Set the status once. | -| `docs/sdk/java/role/delete.mdx`, `docs/sdk/java/resource/delete.mdx`, `docs/sdk/java/tenant/delete.mdx`, `docs/sdk/java/user/delete.mdx` | Nothing (these warnings are new) | Delete warnings naming role assignments, actions and attributes as the related data that goes. | The warnings rest on the spec's "Deletes the object and all its related data", but the specific examples are inferred from the data model. Confirm whether stricter wording is wanted. | -| `docs/sdk/java/user/create.mdx`, `docs/sdk/java/user/sync.mdx` | "The user key must be url-friendly (slugified)." | Removed. | The `UserCreate.key` Javadoc does not say it, and the page's own sample key `auth0\|elon` contains a pipe. State the real rule. | -| `docs/sdk/nodejs/all-tenants.mdx` | The response sample with `allowed` and `message` fields | Kept byte-identical, with the mismatch flagged on the page. | The PDP schema returns `allowed_tenants`. Approve the sample fix and the flag goes. | -| `docs/sdk/python/sync-policy-script/sync-policy.mdx` | "The script avoids duplicating resources and roles by checking their existence before creation" | Replaced with a warning that a second run raises `PermitAlreadyExistsError`. | The script never checks, and the Node.js script's page still claims the opposite. Fix the script or the two pages keep contradicting each other. | -| `docs/sdk/sdks-overview.mdx` | .NET "Get User Permission ✅" in the parity table | Kept, unverified, under an admonition telling readers to confirm against SDK source. | `src/permit/Permit.cs` exposes only `Check`, `BulkCheck` and `BulkCheckVerbose` at the top level. Confirm the row. | -| `docs/status.mdx` | "Check the live status and uptime of Permit.io's Cloud PDP, API, and dashboard." | Lists what the live status page shows: Backend, OPAL, Frontend, Marketing Website, PDP Deltas and PDP Data. | The status page has no Cloud PDP entry, and `https://status.permit.io` does not resolve in DNS, so the page links `permit-io.instatus.com`. Fix the DNS record or the components list. | -| `docs/updates-and-feedback/changelog.mdx` | The Canny changelog as the current changelog, plus "Past entries cover items such as bulk permission checks, the `getUserPermissions` and `getAuthorizedUsers` methods ..." (abridged) | The dated newest entry, May 16 2024, and a table of current sources. | The Canny board has had no entry since May 2024 while a Productlane changelog also exists. Pick the live changelog, or the product needs a current one or a redirect. | -| `docs/updates-and-feedback/roadmap.mdx`, `docs/updates-and-feedback/feature-requests.mdx` | The roadmap on Productlane and the feature requests on Canny, each page describing only its own board | Both pages describe both boards and say what each is for. | Requests and roadmap live on two hosts (Canny with 174 posts, Productlane with 5 ideas). Name the authoritative board. | - -### Screenshots and media - -| Page | Image | What it shows | What the page says | -|---|---|---|---| -| `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | `static/img/ai-security/MCP/food-demo/1.png` and `2.png` | The New Resource panel and the Policy Editor with the ReBAC role `restaurants#child-can-order` and `read` | Both removed. The steps create `child-can-view`, which `utils.py` assigns and `server.py` requests. Needs a retake. | -| `docs/ai-security/integrations/langchain.mdx` | `static/img/ai-security/integrations/langchain/6.png` | An `Everyone` user set on the rule | The page grants `Eligible AI Users`. | -| `docs/ai-security/integrations/langflow.mdx` | `static/img/ai-security/integrations/langflow/5.jpg` | A membership-tier user set built as `user.membership_tier equals resource.class` AND `user.verified equals True` | Removed. No resource on the page defines `class`, and a user set cannot reference a resource attribute. Needs a retake. | -| `docs/ai-security/integrations/langflow.mdx` | `static/img/ai-security/integrations/langflow/8.jpg` | The Policy Editor with `flight:info` unchecked for all three user sets | Removed. The page grants `info` for the Flight Information flow. Needs a retake. | -| `docs/ai-security/integrations/langflow.mdx` | `static/img/ai-security/integrations/langflow/9.jpg` and `10.png` | An If-Else operator `equals` with match text `True`, which cannot match the Permissions Check text outputs, and the model `gpt-4o-audio-preview-2024-10-0…` | Both kept. The page documents the working configuration and warns about the mismatch. A retake would remove the warning. | -| `docs/api/api-with-cli.mdx` | `/ui-videos/api/api-logs.mp4` and `/ui-videos/api/api-log-event.mp4` | The API log screen and one API log event | Both removed with the API log walkthrough, which `permit-logs.mdx` owns. Neither is referenced by any page now. | -| `docs/authentication/hankopermit.mdx` | `static/ui-videos/integrations/authentication/hankopermit/13.jpg` | `post` unchecked on `notes` for both roles, and every action on `Owned Notes` | The step text follows the RBAC policy in `8.jpg`. | -| `docs/authentication/stytch/permit-integration.mdx` | `/ui-videos/authentication/stytch/account-owner-role.png` | Four resources with many actions | The page creates one resource, `Account`, with one action, `view-all`. | -| `docs/authentication/stytch/permit-integration.mdx` | `/ui-videos/authentication/stytch/user-synced.png` | A personal tenant name, a personal avatar, the project "Barclays Planning" and a user key the tutorial never produces | The tutorial syncs one user and the style guide asks for fictional companies. | -| `docs/authentication/supertokens.mdx` | `/img/integrations/supertokens/supertokens-1.png`, `-2.png` and `-3.png` | Steps the page's text already states | Removed with the webinar iframe, which survives as a link. All three are now unreferenced. | -| `docs/embeddable-uis/element/operation-approval.mdx` | `/img/operation-approval/addPermissionForReviewer.png` | The role key `_reviewer_` in lowercase, on a resource spelled `transfar` | The prose and both samples use `_Reviewer_` on `transfer`, and the role assignment `transfer:transfer-1#_Reviewer_`. | -| `docs/getting-started/slack-support.mdx` | `/img/slack/slack-1.png` | The Slack invite page "See what Permit is up to", with real member names | The alt text now describes the invite page. | -| `docs/how-to/build-policies/abac/building-abac-policy.mdx` | `/img/abac-updated/user-set-0.png` | Conditions on `tenant.university` and `tenant.is_full_time` | The steps create user attributes and build a user set on them. | -| `docs/how-to/build-policies/abac/building-abac-policy.mdx` | `/img/abac-updated/policy-screen-check.png` | The set names in the plural, `Full-time Stanford Students` and `Bicycles available after 5pm` | The steps and three other screenshots use the singular names. The page states the difference in one line. | -| `docs/how-to/build-policies/policy-basics.mdx` | The eight `/ui-videos/policy-basics/*.mp4` videos | An older dashboard: a Users item in the nav instead of Directory, a Users and Tenants tab pair, a `default` tenant filter, "FoAz Proxy", "Upgrade to Pro" and the personal address `alfie@gmail.com` | The steps describe the current Directory screen (Users, Instances, Groups tabs; Settings > Manage Tenants; Top Level Access). Re-record, or drop the videos and keep the steps. | -| `docs/how-to/build-policies/policy-basics.mdx` | `/ui-videos/policy-basics/grid-view-policy.png`, `supervisor-policy.png` and `users.png` | A demo role spelled `Supervisior` | All three removed. The videos on the page spell it `Supervisor`, and `admin-policy.png` covers the same point. All three are now unreferenced. | -| `docs/how-to/build-policies/rbac/building-rbac-policy.mdx` | `/img/updated/rbac/rbac-6.png` | All four actions selected for both the Admin and the Customer role | Removed here. The step grants Customer `read` only. The image stays on `build-policies/overview.mdx`, where the text matches it. | -| `docs/how-to/build-policies/rbac/building-rbac-policy.mdx` | `/img/updated/rbac/rbac-7.png` | The old **Users** navigation item | Removed. The step tells the reader to open **Directory**. Needs a retake of the current navigation. | -| `docs/how-to/build-policies/rbac/building-rbac-policy.mdx` | `/img/updated/rbac/rbac-8.png` | The user key and email `john@prtmit.io`, a typo for `permit.io` | The steps and the sample use `john@permit.io`. No prose depends on the typo. | -| `docs/how-to/build-policies/rebac/building-rebac-policies.mdx` | `/ui-videos/rebac/assign-resource-instance.png` | `Docs#Admin` assigned in the diagram, and the row `Folder / Docs / Editor` in the Assigned Instances form below it | The steps name only the field labels (Resource Type, Instance, Resource Role), so no prose depends on the mismatch. | -| `docs/how-to/policy-guard/policy_guard.mdx` | `/img/policy-guard/lock.png` and `/img/policy-guard/scope.png` | Mockups of an unreleased Policy Guard UI, one carrying the banner "Conceptual PREVIEW, Currently available ONLY AS API" | Both removed. The page says Policy Guards are managed with the API. `diagram.png` stays. | -| `docs/how-to/sync-users.mdx` | `/ui-videos/how-to/sync-users/1.png` and `2.png` | A navigation item labeled **Users**, and the Add user button | Both removed. The page calls the screen **Directory**, and `3.png` matches the field table and stays. | -| `docs/integrations/SCIM/OKTA.mdx` | `static/.../dashboard-1.jpeg` | The Base URL host `permit-scim-okta.permit.io` | The page documents `scim.permit.io`. Kept with neutral alt text; needs a retake. | -| `docs/integrations/SCIM/OKTA.mdx` | `https://i.imgur.com/KRZCbiw.png` | The Okta provisioning form | Kept. The image is hosted on imgur, outside the repository, which is a maintenance risk. | -| `docs/integrations/gateways/kong.mdx` | `https://permit-instructions-files.s3.us-east-2.amazonaws.com/instructions-kong-2.png` | The plugin form with `Config.Opa Port` set to `7766`, the PDP port | Removed. The page points the plugin at the proxy on `8080`. A local copy sits at `static/img/integrations/kong/kong-2.png`. | -| `docs/integrations/gateways/kong.mdx` | `/img/updated/kong/kong-1.png` and `static/img/integrations/kong/kong-api-key.png` | The old dashboard label "Copy SDK secret key", and a real employee's name and email | `kong-1.png` removed and replaced with a link to `/overview/get-api-key`. `kong-api-key.png` is unreferenced. | -| `docs/manage-your-account/workspace-settings.mdx` | `mixed-access-level.png` | Real `@permit.io` email addresses | The example now describes "a member". | -| `docs/modeling/feature-flagging.mdx` | `custom-ui-demo/attributes.png` and `custom-ui-demo/resources-with-attributes.png` | `country` and `channel` in a resource's ABAC Options form | Both removed. The step sets them as user attributes, and no replacement image exists, so that step is text only. | -| `docs/overview/create-a-rebac-policy.mdx` | `relation-diagram.png` | Anna as Viewer of Dashboard and Analyst or Editor of Widget A, roles the data steps never create | Kept. The prose says the diagram illustrates the two access paths with example instance names, not the data you create. | -| `docs/overview/create-a-rebac-policy.mdx` | `dashboard-permissions.png` and `widget-permissions.png` | A truncated fifth column, likely Dashboard#Viewer, holding `edit` and `view` | The page says Viewer has `view` only. | -| `docs/overview/local-authorization-microservice.mdx` | `/img/updated/walkthroughs/local-policy-check/pulling-pdp.mp4` and `running-pdp.mp4` | Pulling and running the PDP container | Both removed with the duplicated steps, which `run-pdp.mdx` owns. Neither has a counterpart there, so both are unreferenced. | -| `docs/overview/perform-policy-check-with-cloud-pdp.mdx` | The page's dashboard screenshots | The user key `user\|987654321` and a `read` permission the prerequisite page never creates | A "Set up the starting state" section states the only precondition, the samples use a `` placeholder, and the prose labels the screenshots as an example environment. | -| `docs/overview/setup-attribute-based-access-control.mdx` | `/img/updated/walkthroughs/abac-guide/setting-policy.mp4` | The `Employee` role granted `read` on `Document`, which makes the page's scenario fail | Removed. Step 5 grants `Employee` `read` on a Public Document resource set instead. | -| `docs/overview/sync-your-first-user-with-sdk.mdx` | `default-tenant.png` | A default-tenant role the walkthrough never assigns | The prose says the default-tenant role does not change, and the alt text describes the screenshot as it is. Retake it, or have the walkthrough assign `Employee`. | -| `docs/permit-mcp-gateway/demos/n8n-linear-mcp-gateway.mdx` | `/img/mcpermit/n8n-linear-demo/execution-blocked.png` | An older gateway denial message, "Permission denied for tool 'save_issue'" | The page cites the `-32004` code and says the message names the tool, because the gateway now returns a longer message. | -| `docs/permit-mcp-gateway/demos/n8n-linear-mcp-gateway.mdx` | `tool-import.png` | The tool import and consent screen | The page says the screen shows Linear's tools with their trust levels and one trust level granted to the workflow. Check that it matches the current consent screen. | - -## Full claims log - -Every claim that the rewrite removed, changed, or kept without verification, with the reason. Entries are grouped by rewrite batch. - -### Batch nexus (`runbooks/edge-pdp-staging-enablement.md` and related pages) - -Source used for Nexus PDP: permitio/cloud-pdp `edge-pdp/` (README, Dockerfile, src/config.rs, health.rs, servers/, supervisor/, dataplane/), `cloud-pdp-core/src/{config.rs,routes/}`, `surrealdb-wrapper/src/config.rs`, runbook `docs/runbooks/edge-pdp-staging-enablement.md`; permitio/next-website `app/nexus-pdp/page.tsx` (early access, 4 GiB, probes, grace period). Container PDP / AuthZen / cache: permitio/PDP `pdp-server/src/`. Note: the Nexus PDP source lives in permitio/cloud-pdp, not permitio/PDP. - -#### Removed or corrected - -- `docs/concepts/pdp/nexus-pdp-deployment.mdx`: "Credentials never reach the child processes." (reason: contradicts source. `edge-pdp/src/supervisor/opa.rs` `build_command` re-adds `PDP_API_KEY` to the OPA child's environment so OPA can authenticate to the query loopback; only the NATS leaf lacks it. Rewritten to say that.) -- `docs/concepts/pdp/nexus-pdp-deployment.mdx`: "no ability to reach Permit's management API" for a compromised PDP (reason: could not verify what the `PDP_API_KEY` bundle can do against api.permit.io; the binary lacks a client, but a stolen key is not bound by the binary. Kept only "holds one environment's data and credentials".) -- `docs/concepts/pdp/nexus-pdp-deployment.mdx`: "the container is killed mid-flush and the durable event store is corrupted, forcing a cold start on the next boot" (reason: source says only that SIGKILL can hit the leaf mid-flush (`config.rs` drain_timeout doc); corruption and forced cold start not verified. Softened to "killed before its event store finishes flushing".) -- `docs/concepts/pdp/nexus-pdp-deployment.mdx`: "Cold start can take minutes" / "minutes of startup" (reason: no published figure; staging note in config.rs shows ~17 s for 306 MB. Replaced with "takes longer as your data grows".) -- `docs/concepts/pdp/nexus-pdp-how-it-works.mdx`: "Bulk-loading pre-built database files is substantially faster than the container PDP's cold start" (reason: could not verify; no comparative measurement.) -- `docs/concepts/pdp/nexus-pdp-how-it-works.mdx`: "Nothing is dropped, and nothing is trimmed before every PDP that needs it has confirmed it" (reason: contradicts the gap detector, which exists because the stream can drop changes a lagging PDP has not acknowledged. Rewritten: retained until acknowledged, and a PDP behind the oldest retained change rebuilds from a snapshot.) -- `docs/concepts/pdp/nexus-pdp-how-it-works.mdx`: "Interest is held by the subscription's existence, not by an open connection; a PDP that is disconnected for minutes resumes exactly where it left off" (reason: "minutes" unverified retention bound; kept "resumes from its last acknowledged position".) -- `docs/concepts/pdp/nexus-pdp-how-it-works.mdx`: "Permit currently sizes it at 4 GiB" reworded to "Start with 4 GiB" (source: next-website page "about 4 GiB of memory to start"). -- `docs/concepts/pdp/nexus-pdp-feature-parity.mdx`: "OpenTelemetry (OTLP traces, metrics, logs) | ❌ | 🚧 On the roadmap" row and legend (reason: roadmap claim; STYLE_GUIDE forbids planned features.) -- `docs/concepts/pdp/nexus-pdp-feature-parity.mdx` and nexus-pdp.mdx: "We ship new capabilities to Nexus PDP continually, and this page is updated as they land" / "Feature parity ... is in progress and ships continually" (reason: roadmap/dated wording. Replaced with a dated "as of September 2026" note.) -- `docs/concepts/pdp/nexus-pdp.mdx`: "ground-up rewrite of the PDP runtime" (reason: marketing framing; source shows Nexus composes cloud-pdp libraries, not a rewrite of pdp-v2.) -- `docs/concepts/pdp/nexus-pdp.mdx`, overview.mdx, configuration, how-it-works: "Contact us / talk to us / tell us" mailto links for access and latency validation replaced with https://www.permit.io/demo (sales intent per STYLE_GUIDE). Configuration keeps support@permit.io for variable-dependency reports. -- `docs/concepts/pdp/nexus-pdp-configuration.mdx`: "there is no `PDP_CONTROL_PLANE` value to configure" (reason: contradicts source. `edge-pdp/src/config.rs` reads `PDP_CONTROL_PLANE` as an override of the API key's NATS URL. Rewritten: leave it unset unless Permit support asks.) -- `docs/concepts/pdp/nexus-pdp-configuration.mdx`: `PDP_DEBUG` default "`false`" and "Include debug detail in authorization responses" (reason: source `cloud-pdp-core/src/config.rs` is `Option` with no default, documented as "extra logging/debug information in OPA requests". Changed to "Unset (off)" and "adds debug information to policy evaluation requests".) -- `docs/concepts/pdp/nexus-pdp-architecture.mdx`: "cannot reach `api.permit.io` for a decision even if it wanted to" (reason: tone; replaced with the verified fact that the binary has no Permit API client, per `edge-pdp/README.md`.) -- `docs/concepts/pdp/overview.mdx`: "Custom cloud PDP deployments are available to enterprise tier customers" (reason: plan-tier claim not verifiable. Kept a contact path without the tier; also removed the personal-style calendly link.) -- `docs/concepts/pdp/overview.mdx`: "All policy changes made through the Permit dashboard or API are immediately available through the AuthZen endpoints" (reason: "immediately" contradicts propagation delay; rewritten to "after the change reaches the PDP".) -- `docs/concepts/pdp/overview.mdx`: OPAL "without having to be dependant on the availability of the Permit.io cloud, or sharing any data with it" (reason: "not sharing any data" contradicts decision logs and Permit-hosted policy data; removed.) -- `docs/concepts/pdp/overview.mdx`: "caching significantly improves performance" (reason: unquantified; replaced with the mechanism.) -- `docs/concepts/pdp/overview.mdx`: AuthZen response examples `{"subjects": ...}`, `{"resources": ...}`, `{"actions": ...}` (reason: contradicts permitio/PDP `search_*.rs`, which return `results` plus `page`. Prose corrected.) -- `docs/concepts/pdp/nexus-pdp.mdx`: long verbatim blockquote from OPA's Policy Performance docs replaced with a paraphrase and link (copyright; claim itself kept). - -#### Kept, verified against source (for the reviewer) - -- Nine readiness-gating components (`edge-pdp/src/health.rs` `GATING`); `/health`, `/health/ready`, `/health/detail` on 7001 (`servers/management.rs`); `/health` and `/healthy` on 7000 (`cloud-pdp-core/src/routes/mod.rs`); public port opens only when ready (README). -- Ports 7000-7003, 8181, 4222, 8222 and defaults of `EDGE_*`, `OPA_TIMEOUT_MS` (800), `EDGE_PARALLELISM` (4), `EDGE_DECISION_LOG_OPT_OUT` (off-only), drain 10 s + child termination 30 s (`config.rs`, `cloud-pdp-core/src/config.rs`); `RUST_LOG` default info (`lib.rs default_env_filter`). -- `SURREAL_ROCKSDB_*` defaults 512 MiB / 256 MiB / 32 / 4 (`surrealdb-wrapper/src/config.rs`, mirroring surrealdb-core). -- Constant-time bearer check against own key, no Permit API client compiled in, foreign-environment keys rejected (README, runbook). -- env_clear for children, 0600 credential files with O_NOFOLLOW (`supervisor/mod.rs`); UID/GID 10001 (Dockerfile); image `permitio/pdp-v3` public (runbook). -- Snapshot SHA-256 verification and fail-closed (`dataplane/snap_reader.rs`); rebuild in side directory with atomic swap and serve-stale (README); readiness does not gate on lag (README). -- Four planes WAL / POLICY_FILES / POLICY_DATA (schema) / SNAP (`config.rs`). -- Nexus PDP endpoints: `/allowed`, `/allowed/bulk`, `/authorized_users`, `/user-permissions`, AuthZen routes and discovery; no `/allowed/all-tenants`, `/allowed_url`, `/local/*`, `/metrics` (`cloud-pdp-core/src/routes/`). -- Early access, enabled per account, 4 GiB to start, probes on 7001, grace period 40 s (permitio/next-website `app/nexus-pdp/page.tsx`). -- Container PDP cache: in-memory or Redis, off by default (`PDP_CACHE_STORE` default `none`), cached handlers for allowed, bulk, user-permissions, authorized_users (permitio/PDP `pdp-server/src/config/cache.rs`, `opa_client/cached.rs`); `/healthy` on the container PDP (`api/health/handlers.rs`); AuthZen `tenant` read from `resource.properties` (`authzen/schema.rs`). - -#### Unverified, kept (low risk, flag to owner) - -- `docs/concepts/pdp/nexus-pdp-feature-parity.mdx`: "A check against a policy that uses condition sets, user sets, or resource sets returns a deny on Nexus PDP, not an error." Consistent with the ABAC design spec in permitio/cloud-pdp (stub `check/abac.rego` defaults to false) but not confirmed by a test. -- `docs/concepts/pdp/nexus-pdp-how-it-works.mdx`: last-writer-wins by (timestamp, transaction ID) with per-transaction atomicity. Referenced as "the ordinary LWW guard" in the cloud-pdp ABAC spec; write-service source not read. -- `docs/concepts/pdp/nexus-pdp-feature-parity.mdx`: "Kong and NGINX integrations" supported on the container PDP (pre-existing row, not re-verified). - -### Batch u1 (`how-to/enforce-permissions` and related pages) - -- `docs/how-to/enforce-permissions/data-filtering.mdx`: "Simplified Partial-evaluation, is an upcoming feature in advanced stages of release, which includes built-in translation to SQL" (reason: unreleased/roadmap wording, could not verify availability; removed) -- `docs/how-to/enforce-permissions/data-filtering.mdx`: "This capability exists in Open Policy Agent (OPA) under the compile API and is already available within Permit's PDP" (reason: reworded to the verifiable mechanism, OPA's Compile API through the exposed OPA port of the PDP container; whether Permit's generated policies partially evaluate cleanly was not verified) -- `docs/how-to/enforce-permissions/data-filtering.mdx`: "PDP-Level Filtering ... filterObjects function ... returns a subset of the objects passed to it based on the policy" (reason: SDK source shows FilterObjects/filter_objects run a bulk check in the SDK, not a PDP-side filter; page now says so) -- `docs/how-to/enforce-permissions/list-role-assignments.mdx`: "Permit is gradually releasing these APIs. The following pages contain the currently available APIs." (reason: dated/roadmap wording; removed) -- `docs/how-to/enforce-permissions/list-role-assignments.mdx`: "This function is paginated and returns a maximum of 100 role assignments per page" (reason: kept, but clarified from PDP source: max 100, REST default per_page 30, Python SDK default 100) -- `docs/how-to/enforce-permissions/list-role-assignments.mdx`: "Using these APIs in the local PDP avoids network latency and provides faster responses" (reason: reworded to the mechanism, the PDP answers from its local policy data without a call to the Permit cloud API) -- `docs/how-to/enforce-permissions/user-permissions.mdx`: "`enable_abac_user_permissions` parameter name is subject to change" (reason: stale; the flag name is verified in permitio/permit-backend user_permissions.rego.tpl and permitio/datasync handlers.go; note removed) -- `docs/how-to/enforce-permissions/user-permissions.mdx`: "Not all SDKs are supporting this feature at this point in time" (reason: dated; replaced with the verified fact that the Node.js and Python functions take no context argument) -- `docs/how-to/enforce-permissions/all-tenants-check.mdx`: "The tenant key isn't required and will be ignored if provided" (reason: kept from the original; not verified in the policy source) -- `docs/how-to/enforce-permissions/all-tenants-check.mdx`: "Currently, using relationship-based access control (ReBAC) doesn't work for the All Tenants Check" (reason: kept as a limitation without "currently"; behavior not verified in the policy source) -- `docs/how-to/enforce-permissions/authorized-users.mdx`: "That feature is performance-intensive and is disabled by default" (reason: default-off verified, the flag is opt-in per request in the Rego template; performance claim kept from original, not measured) -- `docs/how-to/enforce-permissions/url-mapping/url-mapping-check.mdx`: "The SDKs will be updated to support this feature soon" (reason: roadmap wording; replaced with verified fact: Java has permit.checkUrl(), other SDKs have no URL check) -- `docs/how-to/enforce-permissions/url-mapping/url-mapping-check.mdx`: "In the URL Mapping UI ... `example.com/v1/{customer_id}/payments`" (reason: PDP source compares the full URL segment by segment, including scheme and host; example changed to `https://example.com/v1/{customer_id}/payments`) -- `docs/how-to/enforce-permissions/url-mapping/url-mapping-check.mdx`: "Each rule sets the HTTP method, the URL template, the resource, and the action" as a UI description (reason: based on the MappingRule API schema and the existing screenshot; dashboard field labels not verified) -- `docs/how-to/enforce-permissions/url-mapping/regex-url-mapping-check.mdx`: "This feature is currently only available through the Permit.io API & PDP API" (reason: could not verify whether the URL Mapping dashboard supports regex rules; page now says to create regex rules with the API without claiming UI absence) -- `docs/how-to/enforce-permissions/url-mapping/regex-url-mapping-check.mdx`: "Simple URL mapping is supported in PDP version 0.8.0 or higher" (reason: mislabeled; PDP commit 3545c4aa "Integrate regex URL matching" is included in release 0.8.0 and not in 0.7.2, so the note now says regex URL mapping requires 0.8.0. Simple URL mapping: /allowed_url was added 2023-07-23, Docker Hub tag 0.2.18 pushed 2023-06-20 and 0.2.19 pushed 2023-08-02, consistent with 0.2.19) -- `docs/how-to/enforce-permissions/url-mapping/regex-url-mapping-check.mdx`: "The `secret` value is still required for now, even though it isn't used. This will be fixed in a future release of the proxy_configs API." (reason: roadmap; kept only verified facts: API spec lists secret as required, PDP /allowed_url code doesn't use it) -- `docs/how-to/enforce-permissions/url-mapping/configuring-jwks.mdx`: "In order to start using URL Mapping with Permit, you need to add your obtained JWKs ... sending API calls directly from the frontend" (reason: could not verify that URL mapping checks use the environment JWKS; API spec describes the environment `jwks` field as "jwks for element frontend only login"; page now names Permit Elements frontend login as the verified use) -- `docs/how-to/enforce-permissions/url-mapping/fetching-jwks.mdx`: "Via the Backend API ... `https://api.clerk.dev/v1/jwks`" (reason: stale; Clerk docs list `https://api.clerk.com/v1/jwks`, updated) -- `docs/how-to/enforce-permissions/url-mapping/fetching-jwks.mdx`: "If you are planning to use Clerk on a Serverless/Edge Runtime ... `Dashboard > API Keys > JWT Verification Key` ... not in PEM format" (reason: third-party dashboard path, volatile and not needed to obtain a JWKS; removed) -- `docs/how-to/enforce-permissions/url-mapping/fetching-jwks.mdx`: "OneLogin ... send a GET request to `https://.onelogin.com/oidc/2/signing_keys` ... pass a bearer access_token" (reason: replaced with the public JWKS URL `https://{subdomain}.onelogin.com/oidc/2/certs` listed on the OneLogin list-keys page) -- `docs/how-to/enforce-permissions/url-mapping/fetching-jwks.mdx`: SuperTokens doc link `https://supertokens.com/docs/microservice_auth/jwt-verification/index` (reason: 404; replaced with the SuperTokens protect-API-routes page, which shows `/auth/jwt/jwks.json`) -- `docs/how-to/enforce-permissions/url-mapping/fetching-jwks.mdx`: "Obtaining JWKs involves generating key pairs, extracting keys from trusted certificates, utilizing key management systems ... ensuring the integrity and security of online communications" (reason: generic, unsupported claims; removed) -- `docs/how-to/enforce-permissions/data-filtering.mdx`: Couchbase blog link `https://www.couchbase.com/blog/permit-io-couchbase-access-control/` (reason: returned HTTP 403 to a script, likely bot protection; kept, not confirmed live) - -### Batch w1 (`sdk/nodejs` and related pages) - -- `docs/sdk/nodejs/all-tenants.mdx`: "you can use the permit.AllTenantsCheck function" (reason: no such method; the SDK method is `permit.checkAllTenants()` per permit-node src/enforcement/enforcer.ts) -- `docs/sdk/nodejs/all-tenants.mdx`: "send a GET request to the `/allowed/all-tenants` endpoint" (reason: contradicts permit-node, which sends POST) -- `docs/sdk/nodejs/all-tenants.mdx`: response sample with "allowed" and "message" fields (reason: contradicts PDP schema `AllTenantsAuthorizationResult.allowed_tenants` in permitio/PDP horizon/enforcer/schemas.py; sample kept byte-identical and flagged on the page, fix logged) -- `docs/sdk/nodejs/bulk-requests-examples.mdx`: "each user object in the `users` array is of type UserCreate and contains the user's details such as username, email, password" (reason: contradicts API; body field is `operations`, UserCreate has no username or password) -- `docs/sdk/python/sync-policy-script/sync-policy.mdx`: "The script avoids duplicating resources and roles by checking their existence before creation" (reason: contradicts the script code, which never checks; a second run raises PermitAlreadyExistsError. Replaced with a warning; cross-page conflict with the Node.js script logged in codefix_w1.md) -- `docs/sdk/nodejs/user/sync-user.mdx`: "sync (save) a user's information to the Permit.io cloud and PDP ... upon user creation" and "should be used for the initial creation" (reason: stale; users.sync creates or updates, per permit-node src/api/users.ts) -- `docs/sdk/nodejs/user/create-user.mdx`, `sync-user.mdx`: "You can use anything for this ID; the user email" (reason: conflicts with "key must be url-friendly"; replaced with a unique, URL-friendly identifier such as the identity provider user ID) -- `docs/sdk/permit-prisma-extension.mdx`: "Resource Synchronization: Keeps your Permit.io policy engine in sync with your database by automatically ingesting resource instances and their relationships" (reason: contradicts permit-prisma src/extension/PermitClientExtension.ts, which syncs resource instances only, not relationship tuples) -- `docs/sdk/permit-prisma-extension.mdx`: "implementing true row-level security" and TL;DR "Seamlessly integrate" (reason: marketing claim, not verifiable; data filtering applies only to findMany) -- `docs/sdk/permit-prisma-extension.mdx`: "Intercepts all Prisma operations" as unconditional (reason: code skips checks when no user is set and for excluded models/operations; documented as a warning) -- `docs/sdk/permit-prisma-extension.mdx`: "Use locally deployed PDP for ABAC and ReBAC policies" (reason: contradicts /concepts/pdp/cloud-pdp-capabilities, where the Cloud PDP supports ReBAC; only ABAC needs an Edge PDP) -- `docs/sdk/permit-prisma-extension.mdx`: "When `enableAttributeSync` is on, resource attributes are automatically synced to Permit.io for policy evaluation" (reason: in code, enableAttributeSync and enableResourceSync trigger the same instance sync and send only the record's `attributes` field; reworded) -- `docs/sdk/ruby/user/sync_user.mdx`: "sync (save) a user's information ... upon user creation" and "should be used for the initial creation" (reason: permit-ruby lib/api/users.rb creates or updates the user) -- `docs/sdk/ruby/user/sync_user.mdx`: commented-out link telling readers to use an assignRole function (reason: permit-ruby has no role assignment method; replaced with API endpoint links) - -### Batch u2 (`getting-started/_quickstart-parts` and related pages) - -- `docs/getting-started/_quickstart-parts/_quickstart_{nodejs,python,python_sync,golang,java,dotnet,ruby}.mdx`: "This means that your user data **never** goes outside your system, **keeping security high**." (reason: contradicts product behavior; users, roles, and attributes synced through the Permit API are stored in the Permit control plane. permit-node `src/api/deprecated.ts` says these API calls go outside your local network.) Replaced with a note on where checks run and where user data is stored. -- Same partials: "Permission checks are being run against the PDP container that's running locally on your machine - offering minimal latency and without leaving your network." (reason: only true for a container PDP; the intro partial defaults to the Cloud PDP tab. Rewritten to say checks go to the configured PDP URL and a container PDP evaluates checks on your machine.) -- Same partials: "You can also pass the entire decoded JWT, to include attributes about the user." (reason: could not verify; SDK `check()` signatures take a user key or a user object with `key` and `attributes`, not a JWT.) -- Same partials: "The tenant passed in needs to be either the **tenant id** or the **tenant key**." (reason: could not verify that tenant IDs are accepted in `permit.check()`; pages now say "tenant key".) -- `_quickstart_nodejs.mdx`, `_quickstart_python.mdx`: "There attributes are merged (and override) user and resource attributes that were persisted to the permit API." (reason: could not verify merge/override semantics in SDK or docs sources.) -- `_quickstart_nodejs.mdx`, `docs/sdk/nodejs/quickstart-nodejs.mdx` prose: implied default that the SDK "returns false if you get a timeout / network error" (reason: contradicts permit-node `src/config.ts`, where `throwOnError` defaults to `true`). Prose no longer states a default; the code comment is logged in codefix_u2.md. -- `_quickstart_golang.mdx`: "`User`: ... this can be created using `models.NewUserCreate("user_key")`" and "`resource`: ... `models.NewResourceCreate("resource_key")`" (reason: contradicts permit-golang; `Check()` takes `enforcement.User`/`enforcement.Resource` built with `enforcement.UserBuilder`/`ResourceBuilder`.) -- `_quickstart_golang.mdx`: "Assuming a Node.js app made up of a single file, with the `permitio` and `express` modules installed." above the Go example (reason: wrong language). -- `_quickstart_golang.mdx`: heading "Full app example (includes ABAC RBAC and terraform )" (reason: could not verify ABAC/RBAC coverage in the permit-go-example README; kept only the verified Terraform configuration.) -- `_quickstart_java.mdx`: "Example application using Spring framework" for permit-java-example (reason: could not verify Spring in the repository README; README describes "a simple blog application". RBAC, ABAC, ReBAC, and Terraform coverage verified in the README.) -- `_quickstart_intro.mdx`: image alt texts were swapped ("Copy secret key from user menu" on the Projects screen screenshot, and vice versa). Fixed to describe each screenshot. -- `_quickstart_intro.mdx`: "Cloud PDP is a **managed, production-ready** service" (reason: "production-ready" is a marketing qualifier; kept "managed" and the verified RBAC/ReBAC support and no-ABAC limit from `/concepts/pdp/cloud-pdp-capabilities`.) -- `_quickstart_python_sync.mdx`: full example pinning `permit==1.0.0rc1` with `permit.write()` (reason: current `permit` package on PyPI is 2.8.3 and `permit/permit.py` has no `write()`; added a warning pending the code fix in codefix_u2.md.) -- `docs/sdk/cpp/quickstart-cpp.mdx`, `docs/sdk/erlang/quickstart-erlang.mdx`, `docs/sdk/kotlin/quickstart-kotlin.mdx`, `docs/sdk/php/quickstart-php.mdx`: "Currently, the SDK is in beta." (reason: could not verify status; the repositories' READMEs don't state beta status, and the C++, Kotlin, and Erlang repositories were last pushed 2025-01-09. The sidebar labels in `sidebars.js` still say "(Beta)"; the coordinator may want to align them.) -- `docs/sdk/erlang/quickstart-erlang.mdx`: implied that permit-erlang is a client SDK (reason: the repository README describes the code as "An Erlang server stub generated by OpenAPI Generator"; the page now says so.) -- Same four pages: hardcoded Slack invite `https://permit-io.slack.com/join/shared_invite/...` (reason: style guide requires `https://io.permit.io/slack`). -- `docs/sdk/php/quickstart-php.mdx`: "Should also work with PHP 8.0." (reason: replaced with the verified constraint from permit-php `composer.json`: `"php": "^7.4 || ^8.0"`.) -- `docs/sdk/sdks-overview.mdx`: Python "Get User Permission" marked 🔴 (reason: contradicts permit-python `permit/permit.py`, which defines `async def get_user_permissions(...)`; changed to ✅.) -- `docs/sdk/sdks-overview.mdx`: rest of the parity table not re-audited row by row. Spot checks that look doubtful but were not changed: .NET "Get User Permission ✅" (`src/permit/Permit.cs` exposes only `Check`, `BulkCheck`, `BulkCheckVerbose` at the top level), Ruby "Get Authorized Users ✅" (`lib/permit.rb` exposes only `check` and `sync_user`). Added an info admonition telling readers to confirm against SDK source. -- `docs/sdk/sdks-overview.mdx`: "It is impossible to implement all the features of the Permit.io API in Terraform due to Terraform limitations and basic design principles." (reason: reworded to the concrete case the table shows, request-time features such as permission checks.) -- `docs/overview/connecting-your-app.mdx`: title "Running a demo" (reason: did not match the page's task; retitled "Connect your app and run your first permission check". URL and anchors unchanged.) - -### Batch w2 (`sdk/golang` and related pages) - -- `docs/sdk/golang/role/Get.mdx`, `docs/sdk/dotnet/role/GetRole.mdx`: "Get a single tenant role" (reason: contradicts SDK and API; roles are environment-level objects fetched from the environment the API key belongs to). -- `docs/sdk/golang/role/Create.mdx`: role `Key` description that referred to a user email and `permit.check` (reason: copy-paste from the user page; contradicts `models.RoleCreate`). -- `docs/sdk/dotnet/role/ListAssignedRoles.mdx`: "If no is tenant provided, all tenants will fetch" (reason: garbled, and the tenant argument is ignored; `Api.cs` `ListAssignedRoles` sends only `user` to `List_role_assignmentsAsync`). -- `docs/sdk/golang/user/UnassignRole.mdx`: parameters described as a payload object with a repeated `ctx` (reason: contradicts `users.go`, which takes positional arguments). The old `#payload` anchor was dropped; no page links to it (checked `grep -rn` over docs and src). -- `docs/sdk/golang/resource/Create.mdx`, `docs/sdk/golang/resource/Update.mdx`: "A actions definition block" (copy-paste prose, rewritten against `models.ActionBlockEditable`). -- `docs/sdk/dotnet/user/CreateUser.mdx`, `docs/sdk/golang/user/Create.mdx`: suggestion to use an email as the user key (reason: conflicts with the URL-friendly key rule stated on the same page; removed rather than asserted). - -Verified and kept: Go `Tenants.Create` returns the existing tenant when the key exists (API spec, POST /v2/facts/{proj_id}/{env_id}/tenants description); .NET `SyncUser` uses the replace-user PUT endpoint (`Api.cs` `Replace_userAsync`); Go `GetAssignedRoles` pagination limits 1-100 (`users.go`, `isPaginationInLimit`, `DefaultPerPageLimit`). - -### Batch w3 (`sdk/java` and related pages) - -- `docs/sdk/java/user/create.mdx`: "The user key must be url-friendly (slugified)." (reason: could not verify; the `UserCreate.key` Javadoc in permit-java does not say this, and the page's own sample key `auth0|elon` contains `|`) -- `docs/sdk/java/user/sync.mdx`: "The user key must be url-friendly (slugified)." (reason: same as above) -- `docs/sdk/java/user/sync.mdx`: "sync (save) a user's information to the Permit.io cloud and PDP (Policy Decision Point) upon user creation" (reason: reworded; source shows `sync()` is an upsert via `PUT` that creates or updates, so "upon user creation" only was incomplete) -- `docs/sdk/java/role/delete.mdx`, `resource/delete.mdx`, `tenant/delete.mdx`, `user/delete.mdx`: "The id of the . This is the unique key of the ." (reason: contradictory; replaced with "key or ID", per the API spec path parameter "Either the unique id ... or the URL-friendly key") -- `docs/sdk/java/resource/update.mdx`, `role/update.mdx`: `name` listed as required for `ResourceUpdate` / `RoleUpdate` (reason: contradicts source; every field in `ResourceUpdate` and `RoleUpdate` is optional) -- `docs/sdk/java/resource/create.mdx`, `resource/update.mdx`, `role/create.mdx`, `role/update.mdx`: fields `roles`, `relations`, `extends`, `grantedTo`, `attributes` added (verified in `openapi/models/ResourceCreate.java`, `ResourceUpdate.java`, `RoleCreate.java`, `RoleUpdate.java`; not removals, listed for reviewer awareness) -- Delete warnings added on the four delete pages are based on the API spec descriptions "Deletes the and all its related data" (and for roles, "This includes any permissions granted to said role"). The specific examples (role assignments, actions, attributes) are inferred from the Permit data model; confirm with the owner if stricter wording is wanted. - -### Batch u3 (`overview/perform-policy-check-with-cloud-pdp.mdx` and related pages) - -- `docs/overview/perform-policy-check-with-cloud-pdp.mdx`: "It is **fully managed and eventually consistent**. Use it to try Permit and for production workloads that don't require strict read-your-own-writes guarantees." (reason: could not verify the Cloud PDP consistency model in docs or source; cloud-pdp-capabilities does not state it) -- `docs/overview/perform-policy-check-with-cloud-pdp.mdx`: "keep all authorization traffic **inside your own VPC**" (reason: reworded to "checks run inside your own network") -- `docs/overview/perform-policy-check-with-cloud-pdp.mdx`: "The check function can accept various arguments beyond the user and resource." (reason: vague; replaced with a link to /how-to/enforce-permissions/check) -- `docs/overview/perform-a-local-policy-check.mdx`: "Best practices for production deployments" listed as covered by the target page (reason: contradicts the target page, which does not cover it) -- `docs/overview/local-authorization-microservice.mdx`: "Scrape it with your monitoring stack to track request latency, decision counts, and errors" and metrics at `http://localhost:7766/metrics` (reason: contradicts PDP source. pdp-server on port 7000 routes /health, /ready, /healthy, /redoc, /scalar and authz APIs, and falls back to horizon, which registers no /metrics route. /metrics is OPA's endpoint on 8181, gated by horizon/static/templates/authz.rego.template and PDP_ALLOW_METRICS_UNAUTHENTICATED. Code fix logged.) -- `docs/overview/local-authorization-microservice.mdx`: "`7766`: The main PDP API port" (reason: 7766 is the host port; the container port is 7000 per the PDP Dockerfile `EXPOSE 7000 7001 8181`) -- `docs/overview/local-authorization-microservice.mdx`: removed the duplicated pull and run steps, their two code blocks, and the two videos (`/img/updated/walkthroughs/local-policy-check/pulling-pdp.mp4`, `running-pdp.mp4`), per coordinator note that run-pdp owns "run the PDP container". The videos have no counterpart on run-pdp; the coordinator may move them there. -- `docs/overview/local-authorization-microservice.mdx`: WhatsNext items "Create user and resource attributes / Define your first User and Resource Sets / Create your ABAC policy rules" (reason: replaced by descriptive next-step links) -- `docs/overview/glossary.mdx`: "Checking permissions for the same user key in several environments in the same month counts as one MAU." and "MAU is the count of unique user keys ... across your workspace (organization)" (reason: could not verify the billing counting rule; workspace-usage.mdx only says unique users per month) -- `docs/overview/glossary.mdx`: "Billing is calculated per workspace, based on MAU" (reason: contradicts workspace-usage.mdx, which says MAU and tenants; reworded) -- `docs/overview/glossary.mdx`: "though most teams need only one" (workspaces) (reason: could not verify) -- `docs/overview/glossary.mdx`: "It is recursive, and a critical part of a secure access control system. It includes features such as meta roles, meta audit logs, and API logs." plus the external devops.com link (reason: could not verify feature names; replaced with a member roles link) -- `docs/overview/glossary.mdx`: "In Permit, the PDP is a Docker container ... often deployed as a sidecar" (reason: stale; the managed Cloud PDP also exists) -- `docs/overview/why-permit.mdx`: "so you don't have to build permissions again", "Permit covers all three layers, not only the enforcement building blocks", "delegate parts of access control to your end users safely" (reason: marketing, unverifiable) -- `docs/overview/best-practices.mdx`: "run Permit checks in read-only mode" (reason: no read-only mode found; reworded as calling permit.check() next to the existing check and logging both) -- `docs/overview/best-practices.mdx`: Slack link `https://io.permit.io/docs-to-slack` changed to `https://io.permit.io/slack` (style guide) -- `docs/overview/get-api-key.mdx` and `docs/overview/use-the-permit-api-and-sdk.mdx`: image alt texts were swapped ("Copy secret key from user menu" was on the Projects screen screenshot); corrected on get-api-key, images removed from use-the-permit-api-and-sdk (duplicate steps now link to get-api-key) - -### Batch u4 (`how-to/sync-users.mdx` and related pages) - -- `docs/how-to/sync-users.mdx`: "We do plan to release a Policy Editor Element (https://permitio.canny.io/feature-requests/p/policy-editor-element), which will allow users to define their own policies within safe limits" (reason: roadmap/planned feature; style guide forbids describing unreleased features. Removed, kept the pointer to building such UIs on the Permit API) -- `docs/how-to/sync-users.mdx`: "you should use the `assign.role` function" (reason: no such function; replaced with `permit.api.users.assignRole()` / `assign_role`, verified in permit-node src/api/users.ts and permit-python permit/api/users.py) -- `docs/how-to/sync-users.mdx`: "The API `Create User` function will not assign the user with a role" (reason: stale; UserCreate in https://api.permit.io/v2/openapi.json has a `role_assignments` field. Reworded: without `role_assignments` the user has no roles) -- `docs/how-to/sync-users.mdx`: "The user key must be url-friendly (slugified)" (reason: imprecise; replaced with the key pattern `^[A-Za-z0-9|@+\-\._]+$` from the OpenAPI UserCreate schema) -- `docs/how-to/sync-users.mdx`: considered "API returns 201 when it creates the user" from the OpenAPI description; not kept because the Postman screenshot on sync-your-first-user shows `200 OK` for a create. Page says "returns the created user, or 409". -- `docs/overview/sync-application-data-into-permit.mdx`: "Security: Minimizes manual interventions" / "Efficiency" / "Consistency" SCIM benefit bullets (reason: generic marketing claims, removed) -- `docs/overview/sync-application-data-into-permit.mdx`: "SCIM sends Lisa's information to Permit.io, which creates her user and assigns her predefined roles" (reason: role assignment through SCIM only verifiable via Okta group push in integrations/SCIM/OKTA.mdx; example reworded to user creation, with a pointer to the Okta group mapping) -- `docs/overview/sync-application-data-into-permit.mdx`: title changed to "Plan your User Sync Strategy"; page is not listed in sidebars.js (not an issue I can fix; coordinator may want to add it or leave it orphaned) -- `docs/overview/sync-your-first-user-with-sdk.mdx`: title "Sync your First User" (implied SDK in URL) retitled "Sync your First User with the API" to match the cURL/Postman walkthrough (URL unchanged) -- `docs/overview/sync-your-first-user-with-sdk.mdx`: "while keeping the `Employee` role in the default tenant" (reason: the walkthrough never assigns Employee; assign-role sample assigns `admin`. Prose says the default-tenant role doesn't change; alt text describes the screenshot as-is. Screenshot `default-tenant.png` should be retaken or the walkthrough should assign `Employee`) -- `docs/overview/sync-your-first-user-with-sdk.mdx`: "Permit is API-first: everything you can do in the UI, you can also do with the API" (reason: absolute claim not verifiable; softened to "Everything you did with the API in this walkthrough, you can also do in the Permit dashboard") -- `docs/overview/sync-applications-data.mdx`: SDK names "`users.sync`, `tenant.create`, `resource_instances.create`, `relationship_tuples.create`" (reason: mixed languages; Node names verified as `permit.api.users.sync`, `tenants.create`, `roleAssignments.assign`, `resourceInstances.create`, `relationshipTuples.create` in permit-node src/api/api-client.ts; Python snake_case names verified in permit-python permit/api/api_client.py. Table lists both) -- `docs/overview/sync-applications-data.mdx`: alt text "Tenant Attributes" on the user-attributes screenshot and "Empty Resource Screen" on the resource-instance screenshot (reason: wrong alt text, replaced) -- `docs/overview/sync-applications-data.mdx`: relationship tuple `tenant` "If the resource instances don't exist yet, the tenant is required to create them, otherwise it is ignored" (reason: OpenAPI RelationshipTupleCreate says a disagreeing tenant is rejected when exactly one instance exists; reworded to the spec) -- `docs/overview/configure-your-first-rbac-policy.mdx`: "Tick the actions ... `create`, `read`, `publish`" (reason: contradicts the check-policies.mp4 video, which checks `create`, `delete`, `publish`; prose now matches the video) -- `docs/overview/setup-attribute-based-access-control.mdx`: user set conditions "`department` equals `Engineering`, `training_status` equals `certified`" vs scenario "R&D department ... completed training" (reason: contradiction. Frames of user-set.mp4 show Engineering/certified with user set name "R&D Certified Employee"; scenario, attribute examples and steps now match the video) -- `docs/overview/setup-attribute-based-access-control.mdx`: "Define an Engineering user as someone permitted to read standard documents but restricted from accessing highly classified documents" (reason: the video's role is `Employee`, and a role with `read` on `Document` can read every document, including resource-set documents, because permit.root allows when any policy allows (permitio/generated-policy-example root.rego). Replaced with an accurate scenario table and a warning; owner may want to re-record setting-policy.mp4 with the Employee role granted on a non-classified resource set) -- `docs/overview/setup-attribute-based-access-control.mdx`: added "The Cloud PDP doesn't evaluate ABAC policies" (source: docs/concepts/pdp/cloud-pdp-capabilities.mdx) -- `docs/overview/create-a-rebac-policy.mdx`: "A resource cannot be its own parent. If a resource requires a self-relation, consider using an alternative relation type such as owner or container." (reason: could not verify; removed) -- `docs/overview/create-a-rebac-policy.mdx`: "When you define the relation, Permit automatically creates the matching roles in the Policy Editor." (reason: could not verify; removed) -- `docs/overview/create-a-rebac-policy.mdx`: Dashboard permissions "Analyst: view, add-widget, edit" (reason: dashboard-permissions/widget-permissions screenshot shows Dashboard#Analyst with add-widget, remove-widget, view; prose now matches. The truncated fifth column in that screenshot (likely Dashboard#Viewer) shows edit and view, while the page says Viewer: view only. Kept "view"; screenshot should be checked) -- `docs/overview/create-a-rebac-policy.mdx`: user emails, instance keys (`johnsmith`, `annasmith`, `data`, `data_consumption`) and UI labels added from frames of creating-users-rebac.mp4, create-resource-instances-rebac.mp4, assign-instance-roles-rebac.mp4 -- `docs/overview/create-a-rebac-policy.mdx`: relation-diagram.png shows Anna as Viewer of Dashboard and Analyst/Editor of Widget A, which the data steps never create (kept image with generic alt text; owner may want a diagram that matches the walkthrough data) -- `docs/overview/advanced-authorization-queries.mdx`: "`permit.authorized_users`" and "`permit.GetUserPermissions`" presented as universal names (reason: Node SDK has no filterObjects or authorized users function (permit-node src/index.ts: check, bulkCheck, checkAllTenants, getUserPermissions); Go has BulkCheck, FilterObjects, GetUserPermissions, no authorized users; Python has bulk_check, filter_objects, authorized_users, get_user_permissions. Table lists per SDK) -- `docs/overview/advanced-authorization-queries.mdx`: "Alice can read Blog Post 1, 2, 3" etc. describe the scenario, but the linked samples use other data (anna@smith.com/contract, repo, bob@example.com). Page now says samples show the call shape with other names. -- `docs/overview/access-requests-and-approvals.mdx`: text steps added only from docs/embeddable-uis/embedding-elements.mdx, element/access-request.mdx, element-login.mdx, element/user-management.mdx; the "Setting up Permit" and "Building the policy" steps link to owner pages instead of describing video-only content -- `docs/overview/access-requests-and-approvals.mdx`: button name differs between docs: "Get Code" (embedding-elements.mdx) vs "Generate Code" (access-request.mdx). Page uses "Generate Code"; one of the source pages is stale. - -### Batch w4 (`quick-start/{express,fastapi,flask,django,nest}.mdx` and related pages) - -#### Claims - -- `docs/quick-start/{express,fastapi,flask,django,nest}.mdx`: "A **Free Post** resource set filters non-premium posts ... This is a ReBAC setup." (reason: wrong. permit-cli `source/templates/blogging-platform.tf` defines `Free_Post` as a resource set with the condition `resource.premium equals false`, which is ABAC. Rewritten as ABAC; the Post-to-Comment role derivation is described as ReBAC.) -- same 5 files: "As users become **Authors**, they gain access to create and update blog posts and manage comments." (reason: contradicts the template. The top-level Author role has `Post:create`, `Post:read`, `Comment:read`. Update and moderation come from the resource roles Post#Author and Comment#Moderator. Replaced with a table built from the template.) -- same 5 files: "the person who creates a post automatically becomes a **Comment Moderator**" (reason: imprecise. The template derives Comment#Moderator from the Post#Author role on the parent post, not from creating the post. Rewritten.) -- same 5 files: "This setup combines ABAC and ReBAC to enforce flexible and secure permissions." (reason: marketing wording; removed.) -- same 5 files: "To check the available templates, run `permit template list`" (reason: wrong command. permit-cli has `source/commands/env/template/list.tsx`, so the command is `permit env template list`. Prose fixed; the matching code block is in codefix_w4.md.) -- same 5 files: Dashboard role assignment steps "Beside the user, click on the **Add Instance Role** button ... Select tenant **(default)**" (reason: contradicts the page's own screenshot `user-access.png`, which shows the **Edit User** panel with **Permissions Per Tenant**, **Default Tenant**, and **Top Level Access**. Instance access is a different control. Rewritten to match the screenshot and linked to /how-to/sync-users.) -- same 5 files: "The PDP server runs on port `7766` by default. You can change the port if needed." (reason: `permit pdp run` hardcodes `-p 7766:7000` in permit-cli `source/components/pdp/PDPRunComponent.tsx`, and has no port option. Kept 7766, removed "you can change the port".) -- same 5 files: API key steps "Click on **Projects** ... three dots ... **Copy API Key**" duplicated inline (reason: owned by /overview/get-api-key; replaced with a link. The old link to /overview/connecting-your-app/#1-get-your-permit-environment-api-key is gone.) -- `docs/quick-start/nest.mdx`: "The `getPosts` handler returns a secret message and is protected by the guard. Just like a middleware." and "Since the blog application can have various elements like creating a post, commenting, editing, etc., `/posts` to demonstrate access control." (reason: fragment and garbled sentence; rewritten.) -- `docs/quick-start/{express,nest}.mdx`: "Conclusion" recap sections removed (meta-commentary; no inbound links). - -#### Added claims (verified) - -- "The Cloud PDP doesn't evaluate ABAC rules, so run the container PDP" (source: docs/overview/run-pdp.mdx, Cloud PDP limits admonition). -- "Each check also appears in the **Audit Log** screen" (source: docs/overview/local-authorization-microservice.mdx, `PDP_OPA_DECISION_LOG_ENABLED` default `True`). -- Python pages: "The `permit` package installs Pydantic with email validation" (source: permit-python `requirements.txt`, `pydantic[email]`). -- Flask: the `Permit` class from `permit` is the asyncio client; sync client exists (source: permit-python `permit/sync.py`). -- Nest: guard returning `false` gives HTTP 403 `{"message":"Forbidden resource","error":"Forbidden","statusCode":403}` (source: `static/img/quick-start-guide/nest-user-not-permitted.png`, NestJS default). `nest new` projects listen on port 3000 and register `AppController` in `AppModule` (NestJS CLI default scaffold). -- Django: `CsrfViewMiddleware` in the `startproject` MIDDLEWARE rejects POST requests without a CSRF token with 403 (Django documented behavior). - -#### Media removed - -- `docs/quick-start/nest.mdx`: removed `/img/quick-start-guide/next-user-permitted.png` and `/img/quick-start-guide/next-user-not-permitted.png`. The screenshots show a Next.js request to `http://localhost:3000/api/protected/posts` with a `user` header returning `{"secret":"User is permitted"}`; the Nest code serves `GET /posts`, reads `x-user`, and returns `{"message":"You have passed the auth check"}`. Replaced with copyable curl commands and expected output in text. -- `docs/quick-start/nest.mdx`: removed `/img/quick-start-guide/nest-register-user.png`. The response in the screenshot has a `role_assignment` key; the Nest code returns the assignment under `response`, so the screenshot was not produced by this code. Note: `nest-user-permitted.png` / `nest-user-not-permitted.png` exist in static but show `POST /posts` with a JSON body, which also does not match the Nest code (GET with `x-user` header), so they were not used. -- `docs/quick-start/{fastapi,flask,django}.mdx`: removed `/img/quick-start-guide/python-register-user.png`, `python-user-permitted.png`, `python-user-not-permitted.png`. These images are Express output: the register response uses the Express `response` key (Python code returns `role_assignment`), and the posts responses say "You are authorized to create a post" / "You are not authorized to create a post" (the Express messages; the Python code returns "User is permitted" / "User is not permitted"). `python-register-user.png` is byte-for-byte the same screenshot as `express-register-user.png`. Replaced with copyable curl commands and expected output in text. - -### Batch w5 (`quick-start/gin.mdx` and related pages) - -- `docs/quick-start/gin.mdx`, `nextjs.mdx`, `rails.mdx`, `spring-boot.mdx`, `aspnet.mdx`: "A **Free Post** resource set filters non-premium posts ... This is a ReBAC setup." (reason: contradicts permit-cli `source/templates/blogging-platform.tf`; a resource set with a `resource.premium equals false` condition is ABAC. Rewritten as ABAC.) -- same five pages: "As users become **Authors**, they gain access to create and update blog posts and manage comments." (reason: contradicts the template; the top-level Author role has only `Post:create`, `Post:read`, `Comment:read`. Rewritten from the template.) -- same five pages: "the person who creates a post automatically becomes a **Comment Moderator**" (reason: contradicts the template; the role derivation gives the Moderator role on comments to a user with the Author role on that post instance, not to whoever creates the post. Rewritten.) -- same five pages: "New users accessing the blog are assigned the **Reader** role and have permission to read posts." (reason: the template's Reader role reads only Free Posts via the resource set; the role is assigned by the app code, not by Permit. Removed.) -- same five pages: "This setup combines ABAC and ReBAC to enforce flexible and secure permissions." (reason: unverifiable "secure" claim, filler. Removed.) -- same five pages: dashboard steps "Beside the user, click on the **Add Instance Role** button" / spring-boot "Click the **Add Role** button" (reason: contradicts the page's own user-access.png screenshot, which shows the Edit User panel with Permissions Per Tenant, Top Level Access, and Save; and `permit.check(user, "create", "Post")` needs a top-level role, not an instance role. Rewritten from the screenshot labels.) -- same five pages: link `/overview/connecting-your-app/#1-get-your-permit-environment-api-key` replaced with `/overview/get-api-key` (fragile partial anchor). -- `docs/quick-start/gin.mdx`: removed screenshots `/img/quick-start-guide/python-register-user.png`, `python-user-permitted.png`, `python-user-not-permitted.png` (reason: wrong for this page; byte-identical to the express/python/rails/spring/dotnet images, they show a register response with a `response` key (Gin returns `role_assignment`), a `/posts` request with a JSON body (Gin reads the `X-User` header), and messages "You are authorized to create a post" (Gin returns "Post created successfully"). Replaced with curl commands and expected output from the page's code.) -- `docs/quick-start/rails.mdx`: removed `/img/quick-start-guide/next-register-user.png` (reason: Next.js screenshot; shows `POST http://localhost:3000/api/register`, a route the Rails app does not have) and `rails-user-permitted.png`, `rails-user-not-permitted.png` (reason: byte-identical to the shared express images; show port 8000 and messages "You are (not) authorized to create a post", while the Rails controller returns "User is (not) permitted"). -- `docs/quick-start/spring-boot.mdx`: removed `spring-register-user.png`, `spring-user-permitted.png`, `spring-user-not-permitted.png` (reason: byte-identical to the shared express images; port 8000, `response` key, and messages do not match the Spring controller, which returns `role_assignment` and "User is (not) permitted" on port 8080). -- `docs/quick-start/spring-boot.mdx`: "use the `curl` command to make a request to the `/check-permission` endpoint" (reason: the code defines `POST /posts`; fixed in prose). ":::info You can grant authorization programmatically as well." (reason: vague; replaced with a link to /how-to/sync-users.) -- `docs/quick-start/aspnet.mdx`: removed `dotnet-register-user.png`, `dotnet-user-permitted.png`, `dotnet-user-not-permitted.png` (reason: byte-identical to the shared express images; `response` key and "You are (not) authorized to create a post" messages do not match the C# handlers, which return `role_assignment` and "User is (not) permitted"). -- `docs/quick-start/aspnet.mdx`: "The Permit SDK is initialized with the `PERMIT_API_KEY` ... and the `PDP_URL`" (reason: contradicts the code, which hardcodes `http://localhost:7766`; prose now describes actual behavior, code fix logged). Page title changed from "ASP.NET Application" to ".NET app" because the sample is an `HttpListener` console app, not ASP.NET Core; sidebar label in sidebars.js is still "ASP.NET" (coordinator may want to change it). -- `docs/quick-start/nextjs.mdx`: removed `/img/quick-start-guide/next-user-permitted.png` (reason: shows `{"secret":"User is permitted"}`, but the route handler returns `{"message":"You have passed the auth check"}`). Kept `next-register-user.png` and `next-user-not-permitted.png` (match the code). -- `docs/quick-start/nextjs.mdx`: open risk, not claimed on the page: whether the `permitio` SDK runs in Next.js middleware's default Edge runtime (reason: could not verify; see codefix_w5.md item 3c). -- `docs/quick-start/*` (all five): "Conclusion" sections removed (summary filler); "enterprise-grade", "robust", "high-performance", "secure, scalable" intro phrasing removed (unverifiable marketing). - -### Batch u5 (`concepts/control-plane-and-data-plane.mdx` and related pages) - -#### Removed or corrected - -- `docs/concepts/control-plane-and-data-plane.mdx`: "The PDP's policy engine (OPA or Cedar)" (reason: the permitio/PDP Dockerfile bundles only the OPA binary; no Cedar agent in the image. Page now says the Edge PDP image bundles OPA, the OPAL client, and an API server.) -- `docs/concepts/multi-tenant-authorization.mdx`: "[Tenants are nested under environments](/manage-your-account/projects-and-env#working-with-the-permit-hierarchy)" (reason: anchor does not exist on the target page; replaced with a plain page link) -- `docs/concepts/multi-tenant-authorization.mdx`: "Use the selector at the top left to switch tenants, rename them, and create new ones." (reason: could not verify selector position or rename/create from docs; replaced with Directory screen and All Tenants wording from how-to/sync-users.mdx) -- `docs/concepts/oss-fallback.mdx`: "use Permit's SDKs in passthrough mode, talking directly to the policy engines in your PDPs" (reason: could not verify a "passthrough mode" in any SDK or doc) -- `docs/concepts/oss-fallback.mdx`: "We hope you stay" and external thenewstack open-core link (reason: tone; opinion link) -- `docs/concepts/pdp/cloud-pdp-benchmarks.mdx`: "Throughput scales near-linearly with concurrency — 10 concurrent requests yield roughly 10x throughput with minimal latency increase." (reason: contradicts the page's own methodology, which says throughput is the observed request rate, not capacity) -- `docs/concepts/pdp/cloud-pdp-benchmarks.mdx`: "P50 latency stays under 15 ms" and "suitable for latency-sensitive applications" (reason: restated from the tables as average P50 at or under 12 ms and average P99 under 50 ms; suitability claim unsupported) -- `docs/concepts/pdp/cloud-pdp-capabilities.mdx`: AuthZen paths "POST /v1/access/evaluation", "/v1/access/evaluations", "/v1/subjects", "/v1/resources", "/v1/actions" (reason: contradicts permitio/PDP pdp-server/src/api/authzen/mod.rs, which routes /access/v1/evaluation, /access/v1/evaluations, /access/v1/search/subject, /access/v1/search/resource, /access/v1/search/action; the rate-limit table already used the correct paths) -- `docs/concepts/pdp/cloud-pdp-capabilities.mdx`: "High throughput & data volume – Optimized for large-scale policy checks" and "designed for high data volume and high throughput" (reason: unqualified, and in tension with per-IP rate limits of 200-3000 req/min) -- `docs/concepts/pdp/cloud-pdp-capabilities.mdx`: "Any dashboards, filters, or exports you rely on today continue to work." (reason: could not verify; dated wording) -- `docs/concepts/pdp/cloud-pdp-capabilities.mdx`: support link "https://permit.io/support" (reason: replaced with support@permit.io, used elsewhere in docs) -- `docs/concepts/pdp/cloud-pdp-capabilities.mdx`: container PDP rate limiting "Your responsibility to configure if needed" (reason: no rate-limit layer in the PDP router; now "None built in") -- `docs/concepts/pdp/configuration.mdx`: "minor versions (e.g., 1.2.3 to 1.2.4)" (reason: that is a patch release per SemVer) -- `docs/concepts/pdp/configuration.mdx`: PDP_PORT "Default: 7766" (reason: Dockerfile sets ENV PDP_PORT=7000 and EXPOSE 7000; 7766 is only the binary default and the usual host-side mapping) -- `docs/concepts/pdp/configuration.mdx`: PDP_HORIZON_PORT "use UVICORN_PORT for PDP versions prior to v0.9.0" (reason: copy-paste from PDP_PORT) -- `docs/concepts/pdp/configuration.mdx`: PDP_BACKEND_SERVICE_URL "Default: https://api.permit.io/v2" (reason: horizon/config.py default is {CONTROL_PLANE}/v1) -- `docs/concepts/pdp/configuration.mdx`: PDP_OPA_DECISION_LOG_INGRESS_ROUTE "Default: /v2/decision-logs/ingress" (reason: horizon/config.py default is /v1/decision_logs/ingress) -- `docs/concepts/pdp/configuration.mdx`: PDP_OPA_DECISION_LOG_INGRESS_BACKEND_TIER_URL "Default: https://decision-log-ingress.api.permit.io" (reason: source default is None; value comes from the control plane) -- `docs/concepts/pdp/configuration.mdx`: PDP_CONTROL_PLANE_PDP_DELTAS_API "https://pdp-deltas.api.permit.io", PDP_CONTROL_PLANE_RELAY_API "https://opal-relay.api.permit.io", PDP_CONTROL_PLANE_RELAY_JWT_TIER "https://relay-jwt.api.permit.io" (reason: could not verify; source defaults are localhost and the PDP receives remote config from the control plane. Now "controlled by Permit".) -- `docs/concepts/pdp/configuration.mdx`: OPAL_SERVER_URL "Default: https://opal-v2.permit.io" and OPAL_SERVER_WS_URL "wss://opal-v2.permit.io" (reason: Dockerfile sets https://opal.permit.io; value is controlled by Permit. WS URL is derived from OPAL_SERVER_URL in opal_client/config.py) -- `docs/concepts/pdp/configuration.mdx`: OPAL_INLINE_OPA_LOG_FORMAT "Default: none" (reason: Dockerfile sets OPAL_INLINE_OPA_LOG_FORMAT="http") -- `docs/concepts/pdp/configuration.mdx`: OPAL_FETCHING_CALLBACK_TIMEOUT "Default: 60" (reason: opal_common/config.py default is 10) -- `docs/concepts/pdp/configuration.mdx`: PDP_USE_NEW_AUTHORIZED_USERS "This feature is controlled by the control plane." (reason: could not verify) -- `docs/concepts/pdp/configuration.mdx`: OPA_DECISION_LOG_ENABLED reference missing the PDP_ prefix (corrected) -- `docs/concepts/pdp/configuration.mdx`: link anchor "/integrations/database-access-control/trino-integration#pdp-trino-config-file" (reason: anchor does not exist on the target page; linked to the page) - -#### Kept but not verifiable from source (owner to confirm) - -- `docs/concepts/pdp/configuration.mdx`: "_Added in PDP v0.9.0_" notes on PDP_PORT, PDP_USE_NEW_AUTHORIZED_USERS, PDP_OPA_URL, cache and Horizon variables, and "_Added in PDP v0.9.4_" on ALL_PROXY (reason: no changelog in permitio/PDP; the variables exist in current source) -- `docs/concepts/pdp/configuration.mdx`: PDP_OPA_CLIENT_QUERY_TIMEOUT "0.9.0 and later: 0 means 0 seconds" (reason: Python config confirms "0 means no timeout" for the old server; Rust behavior for 0 not traced) -- `docs/concepts/pdp/configuration.mdx`: UVICORN_NUM_WORKERS (default 1) and GUNICORN_TIMEOUT (default 600) (reason: current PDP starts Horizon with `python -m uvicorn` and no worker or Gunicorn flags (pdp-server/src/state.rs), so these no longer apply; moved under "Settings for PDP versions before v0.9.0", and the pre-0.9 defaults could not be verified) -- `docs/concepts/pdp/configuration.mdx`: ALL_PROXY "proxy must support HTTP/2 and WebSocket connections" and "TLS in TLS is not supported" (reason: not traced in source) -- `docs/concepts/pdp/cloud-pdp-capabilities.mdx`: Cloud PDP rate-limit table values, "ABAC not supported", "custom policy as code not supported", Cloud PDP decision logs "same format" (reason: Cloud PDP service config is not public; consistent with concepts/pdp/overview.mdx) -- `docs/concepts/deployment-options.mdx`: full on-premise "delivered as Kubernetes Helm charts" and light on-premise flow (reason: consistent with diagrams and on-prem docs; not traced in source) - -### Batch w6 (`how-to/use-audit-logs` and related pages) - -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "This feature is currently available to whitelisted organizations only!" and "add you to our VIP whitelist" (reason: could not verify in the API spec or permit-cli source; the endpoint is public in https://api.permit.io/v2/openapi.json; owner should confirm availability) -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "Maximum replay duration: 30 days" (reason: could not verify; not in AuditLogReplayRequest schema) -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "Maximum concurrency: 10 (contact support for higher limits)" (reason: API spec contradicts itself: concurrency_limit says "max: 5" with default 10) -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "Maximum timeout for a session is 60 seconds" (reason: could not verify; spec only has graceful_shutdown_s, "Graceful shutdown time in seconds", default 60) -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "Replay requests may be throttled based on your plan" (reason: could not verify) -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "Certain audit log types may not be replayable (Authorized-users, Bulk check, etc.)" (reason: could not verify) -- `docs/how-to/use-audit-logs/audit-log-replay.mdx`: "`graceful_shutdown_s` | object (optional) | Additional filters to apply to audit logs before replay" and `start_time` type "string" (reason: contradicts API spec: integer, graceful shutdown seconds) -- `docs/how-to/use-audit-logs/types-and-filtering.mdx`: "Max number of results for this api is 10,000" (reason: could not verify; replaced with the List audit logs spec page size of 100; removed by the interrupted agent) -- `docs/how-to/use-audit-logs/types-and-filtering.mdx`: Trust Center ProductOverviewLink (reason: unrelated to audit logs; removed by the interrupted agent) -- `docs/how-to/use-audit-logs/logs-forwarder.mdx`: "Fluent Bit is a lightweight, and highly scalable logging and metrics processor... CNCF graduated project" (reason: marketing, not needed for the task) -- `docs/how-to/use-audit-logs/logs-forwarder.mdx`: unused video imports removed (not a claim; noted for the build) -- `docs/how-to/permit-cli/permit-cli.mdx`: "The Permit CLI is now available only via npm" (reason: stale dated wording) -- `docs/how-to/permit-cli/permit-cli.mdx`: "built with Pastel, using TypeScript and a React-style architecture. Contributions welcome!" (reason: contributor detail, not reader task) -- `docs/how-to/permit-cli/permit-cli.mdx`: index linked `permit opa policy` to the GitOps page (reason: contradicts content; command is documented on permit-cli-policy#opa-policy) -- `docs/how-to/permit-cli/permit-cli-pdp.mdx`: "`--pdpurl` ... (`default: http://localhost:7676`)" (reason: contradicts source/hooks/useClient.ts: pdp check defaults to getCloudPdpUrl(), the Cloud PDP) -- `docs/how-to/permit-cli/permit-cli-pdp.mdx`: check-url "`--pdp-url` ... (default: Cloud PDP)" (reason: contradicts source/commands/pdp/check-url.tsx: default http://localhost:7766) -- `docs/how-to/permit-cli/permit-cli-pdp.mdx`: attribute format "key1=value1,key2=value2" and flag "-resource-attributes" (reason: contradicts source/utils/attributes.ts, which splits on ":"; flag is --resource-attributes) -- `docs/how-to/permit-cli/permit-cli-pdp.mdx`: "display the container ID and name" (reason: could not verify; source prints "The PDP is running on port 7766") -- `docs/how-to/permit-cli/permit-cli-envs.mdx`: `permit env member --role ` (reason: contradicts source/commands/env/member.tsx enum admin/write/read) -- `docs/how-to/permit-cli/permit-cli-envs.mdx`: `--api-key` listed as Required for env copy, env member, env select (reason: contradicts source: optional, CLI prompts or signs in) -- `docs/how-to/permit-cli/permit-cli-envs.mdx`: `--environment-id` flag for env delete (reason: contradicts source: envId -> --env-id) -- `docs/how-to/permit-cli/permit-cli-envs.mdx`: env create "--env-key will be derived from name if not provided" and custom branch "default is set to the environment ID" (reason: could not verify in source) -- `docs/how-to/permit-cli/permit-cli-envs.mdx`: "enable secure blue-green deployment" (reason: marketing, unverified property) -- `docs/how-to/permit-cli/permit-cli-gitops.mdx`: "--inactive ... (Required) ... set the environment to inactive after configuring GitOps (default:false)" (reason: contradicts source: optional boolean, "Do not activate the repository When Validated") -- `docs/how-to/permit-cli/permit-cli-gitops.mdx`: "Use the CLI to modify and fine-tune Open Policy Agent (OPA) Rego policies while maintaining system stability" (reason: no CLI command does this; empty section replaced with links to custom_policy and permit opa policy) -- `docs/how-to/permit-cli/permit-cli-policy.mdx`: "Check this repo for a good [example](https://github.com/daveads/openapispec)" (reason: personal GitHub repo presented as official example; the same URL remains inside a code block, see codefix_w6.md) -- `docs/how-to/permit-cli/permit-cli-policy.mdx`: "`-x-permit` extensions" (reason: contradicts the extension names, which start with x-permit) -- `docs/how-to/permit-cli/permit-cli-api.mdx`: flags `--first_name`, `--last_name`, alias `user-id`, `--attributes ` (reason: contradicts source/commands/api/sync/user.tsx: --first-name, --last-name, alias userId, repeated key:value strings) -- `docs/how-to/permit-cli/permit-cli-api.mdx`: create proxy "`--key` - a unique ID by which Permit will identify the user for permission checks" (reason: contradicts source: "Unique key identifying the proxy config") -- `docs/how-to/permit-cli/permit-cli-api.mdx`: "Simplifies the usage of Permit's API, allowing you to perform most API actions directly through the CLI" (reason: overstated; the CLI covers a few endpoints) -- `docs/how-to/permit-cli/permit-cli-test.mdx`: run audit "`--api-key` - API Key to be used for test generation" (reason: copy error; the key reads audit logs) - -### Batch u6 (`how-to/deploy` and related pages) - -#### Health endpoint and port conflict (resolved) -Source: permitio/PDP `pdp-server/src/api/health/handlers.rs` routes `/health`, `/ready`, `/healthy` to the same `check_all_health` (Horizon direct check + OPA `/health`; 200 `"status":"ok"` or 503 `"status":"error"`). Routes are outside the API-key middleware (`pdp-server/src/api/mod.rs`). Dockerfile sets `PDP_PORT=7000` (binary default 7766 is overridden in the image). Canonical statement now lives in `docs/how-to/deploy/deploy-to-production.mdx#pdp-health-check-endpoints`; other pages link there. Note: `docs/how-to/deploy/on-prem/pdp-deployment.mdx` (not in this batch) uses `/health` on 7766 via the service, which is consistent with this. - -#### Removed or changed claims -- `docs/how-to/deploy/deploy-to-production.mdx`: "PDP will listen on port 7766 by default" (reason: contradicts Dockerfile `ENV PDP_PORT=7000`; container listens on 7000, examples map host 7766). Rewritten. -- `docs/how-to/deploy/deploy-to-production.mdx`: "zero-latency, great performance, high availability, and improved security" (reason: style guide; replaced with the no-network-round-trip mechanism). -- `docs/how-to/deploy/overview.mdx`: "Custom Hosted PDP deployments ... are available to enterprise tier customers" (reason: plan-tier claim could not verify; kept contact route to support@permit.io and https://www.permit.io/demo, dropped tier). -- `docs/how-to/deploy/overview.mdx`: personal link "https://calendly.com/permitio/" (reason: style guide; replaced with https://www.permit.io/demo). -- `docs/how-to/deploy/overview.mdx`: "zero-latency between your application and the PDP" and "improved ... security (no dependency on other clouds)" (reason: style guide; replaced with "no network latency" over loopback for sidecar, per owner decision, and availability when Permit's cloud is unreachable). -- `docs/how-to/deploy/overview.mdx`: "Managed Cloud PDP" (reason: glossary; now "Cloud PDP"). -- `docs/how-to/deploy/cloud-hosts/kubernetes-raw.mdx`: liveness `/health` "returns 503 when the PDP failure rate exceeds the configured threshold", readiness `/healthy` "503 if the Policy Engine's latest policy update fails", startup `/ready` "200 once the Policy Engine has finished loading the policy from the policy store (Git repository)" (reason: contradicts PDP source; all three paths on port 7000 are aliases of the same combined check). -- `docs/how-to/deploy/cloud-hosts/kubernetes-raw.mdx`: env vars `PDP_OPA_CLIENT_FAILURE_THRESHOLD_PERCENTAGE` (10%) and `PDP_OPA_CLIENT_FAILURE_THRESHOLD_INTERVAL` (60s) as configuring the liveness probe (reason: the real variable name is `PDP_OPA_CLIENT_FAILURE_THRESHOLD` (default 0.1) per `horizon/config.py`, and it drives Horizon's internal `/health` on port 7001, not the `/health` served on port 7000; removed). -- `docs/how-to/deploy/cloud-hosts/kubernetes-raw.mdx`: service name "`permit-pdp..svc.cluster.local`" (reason: contradicts `kubernetes/service.yaml` in permit-pdp-deployments-examples, which names the Service `permitio-pdp` on port 80). Prose now says `permitio-pdp`. -- `docs/how-to/deploy/cloud-hosts/gcp-cloud-run.mdx`: "We shared the YAML file that we used" implying the repo file equals the page YAML (reason: repo `gcp/cloud-run.yaml` differs: service `pdpd`, maxScale 100, API key as plain value). Now described as an older variant. -- `docs/how-to/deploy/cloud-hosts/gcp-cloud-run.mdx`: "`watchdog: error` is expected in Cloud Run due to how Cloud Run handles background processes" (reason: cause could not verify; replaced with the verified fact that Horizon reports `ok` when the direct check succeeds regardless of watchdog, per `checkers.rs`). -- `docs/how-to/deploy/cloud-hosts/gcp-cloud-run.mdx`: "Use an Environment-level API key (not Project or Org key) for Cloud Run deployments" (reason: stated without cause; kept the recommendation with the verified reason that org/project keys need `PDP_ACTIVE_*` variables). -- `docs/how-to/deploy/cloud-hosts/gcp-cloud-run.mdx`: link "Get your API Key" pointed to `/api/api-with-cli` (reason: wrong owner page; now `/overview/get-api-key`). -- `docs/how-to/monitoring-pdps/monitoring-pdps.mdx`: "Data Updated: Last data update timestamp" (reason: contradicts the page's own screenshot, where the column is "DATA UPDATES" with counts 0 and 2; now described as a number without asserting its exact semantics). - -#### Kept but not verifiable from source (owner to confirm) -- `docs/how-to/deploy/deploy-to-production.mdx`: "multiply the number of policy objects ... by 6 KB ... 100,000 users, 500,000 resource instances, and 100 tenants needs about 3.5 GB" (reason: could not verify; kept because it is operational sizing guidance with no replacement. Remove if the owner can't confirm.) -- `docs/how-to/deploy/deploy-to-production.mdx`: "CPU: about 200 millicores ... limit of at least 1000 millicores; Memory: about 512 MiB" (reason: not in source; Helm chart defaults are 256m CPU request, 512Mi memory request, 1Gi memory limit, which is close.) -- `docs/how-to/deploy/cloud-hosts/aws-ecs-fargate.mdx`: "Start with 1 vCPU" (reason: could not verify; the repo's example task definition uses 512 CPU units / 1024 MiB.) -- `docs/how-to/monitoring-pdps/monitoring-pdps.mdx`: "Read timeouts during consistent update requests / HTTP 500 during sync operations ... do not indicate disconnects ... typically client-side timeout configuration" and "most red PDPs in production are stopped PDPs" (reason: support guidance, not verifiable from PDP source; kept.) -- `docs/how-to/monitoring-pdps/monitoring-pdps.mdx`: navigation (organization sidebar > Monitoring > Pdps tab, filters) (reason: taken from the existing screenshot only; EAP UI.) - -#### External example repo problems (affect Terraform and Pulumi pages) -- `docs/how-to/deploy/cloud-hosts/terraform.mdx` and `pulumi.mdx`: the permit-pdp-deployments-examples Terraform `main.tf` and Pulumi `__main__.py` install chart version 0.0.2 from `https://permitio.github.io/sidecar`, which returns 404. The chart (including 0.0.2) is served from `https://permitio.github.io/PDP`. Pages now tell the reader to change the repository URL. The example repo itself should be fixed. -- `docs/how-to/deploy/cloud-hosts/terraform.mdx`: example uses Helm provider 2.x `set {}` and `kubernetes {}` blocks with no version pin; Helm provider 3.0.0 (2025-06-18) changed these (terraform-provider-helm CHANGELOG). Page notes it. - -### Batch u7 (`permit-mcp-gateway/index.mdx` and related pages) - -- `docs/permit-mcp-gateway/index.mdx`: "get a secured gateway URL for any MCP server in under 5 minutes" (reason: hype, unverifiable time claim) -- `docs/permit-mcp-gateway/index.mdx`: "A Permit.io account (free tier available)" (reason: plan-tier claim, could not verify in docs; removed) -- `docs/permit-mcp-gateway/index.mdx`: "Advanced Features: enterprise capabilities and roadmap" (reason: roadmap wording not allowed; link text rewritten) -- `docs/permit-mcp-gateway/index.mdx`: "every Permit policy model and feature" (reason: overclaim; narrowed to RBAC, ABAC, ReBAC and next-call policy updates, verified in permit-integration.mdx) -- `docs/permit-mcp-gateway/quickstart.mdx`: "Get a secured MCP Gateway URL in under 5 minutes" (reason: hype, unverifiable) -- `docs/permit-mcp-gateway/quickstart.mdx`: "Add to `.cursor/mcp.json` (Cursor) or your VS Code MCP settings" with an `mcpServers` snippet (reason: contradicts VS Code docs, which use `.vscode/mcp.json` with a top-level `servers` key, https://code.visualstudio.com/docs/copilot/customization/mcp-servers; heading narrowed to Cursor, VS Code prose pointer added). Same change in guide.mdx. -- `docs/permit-mcp-gateway/quickstart.mdx`: "Ask your agent to perform an action ... and verify it works" (reason: vague verify; replaced with an activity-log check on the Agents detail page, verified in audit-logs.mdx "Platform UI: Activity Views") -- `docs/permit-mcp-gateway/guide.mdx`: "Quick Start: First Value in 5 Minutes" section (reason: hype and duplicate of the numbered steps; merged into the steps and verify sections) -- `docs/permit-mcp-gateway/guide.mdx`: "The gateway currently returns all tools in list_tools responses" (reason: dated wording "currently"; kept as stable behavior, matches architecture.mdx) -- `docs/permit-mcp-gateway/guide.mdx`: "Email OTP ... (6-digit code, 5-minute expiry)", SAML SP Entity ID and ACS URL values, full auth-method list details (reason: duplicate of authentication-methods.mdx; replaced with a short summary and link, not a claim problem) -- `docs/permit-mcp-gateway/overview.mdx`: "Enterprise adoption of AI agents is accelerating" (reason: unsupported generalization) -- `docs/permit-mcp-gateway/overview.mdx`: "you get the full power of Permit's policy engine" (reason: hype) -- `docs/permit-mcp-gateway/overview.mdx`: "Minutes to first value" and "The fastest way to get started" (reason: hype) -- `docs/permit-mcp-gateway/overview.mdx`: "Hosted (SaaS) ... Available on all plans" and "The hosted deployment is available for all plans" (reason: plan-tier claim, could not verify) -- `docs/permit-mcp-gateway/overview.mdx`: "Local PDP: low-latency authorization decisions with no external network dependency" (reason: duplicate of enterprise-deployment.mdx and overstated for customer-controlled mode, which still syncs with the cloud control plane; removed with the duplicated deployment section) -- `docs/permit-mcp-gateway/overview.mdx`: "policies and users can be migrated between deployment models" (reason: owned by enterprise-deployment.mdx; removed here, not verified independently) -- `docs/permit-mcp-gateway/overview.mdx`: "Purpose-built for MCP" (reason: marketing phrasing) -- `docs/permit-mcp-gateway/overview.mdx`: "30-day inactivity / 90-day absolute" session expiry (kept: verified in consent-service.mdx "Session expiry" table; also in guide.mdx with a link) -- `docs/permit-mcp-gateway/overview.mdx`: "you may not need the gateway today, but it is designed to be adopted incrementally" (reason: soft marketing; rewritten as a plain statement) -- `docs/permit-mcp-gateway/overview.mdx`: "Azure AD" in comparison table renamed "Microsoft Entra ID" (reason: product rename) -- `docs/permit-mcp-gateway/overview.mdx`, `docs/permit-mcp-gateway/index.mdx`: Calendly demo link replaced by https://www.permit.io/demo - -### Batch w7 (`how-to/deploy` and related pages) - -Source used: private repo `permitio/permit-deployments` (branch main), files `on-prem/scripts/install-permit-platform.sh`, `on-prem/scripts/push-images-to-registry.sh`, `on-prem/internal-side.sh` (generates the package `values.yaml`), `on-prem/INTERNAL-README.md`, and chart templates `tls-secret.yaml`, `frontend-service.yaml`, `permit-services.yaml`, `policy-sync-validation.yaml`. Copies in `scratchpad/w7src/`. - -#### Owner must confirm (installer behavior that conflicts with the docs) - -- `docs/how-to/deploy/on-prem/installation.mdx`, `quick-start.mdx`: "(no flags) Deploy to production Kubernetes (EKS, GKE, AKS)" / targets-table row "None: Deploys to the cluster in your current kubectl context" (reason: contradicts install-permit-platform.sh. Only `--gke` sets `ENVIRONMENT=production`. With no target flag, `create_cluster()` runs `kind create cluster`, and `run_migrations()`/`deploy_platform()` read the backend tag with `docker exec permit-platform-on-prem-control-plane crictl images` unless OpenShift or GKE mode is set, so a no-flag run on EKS/AKS fails. Resolved in prose: the targets table documents `--gke` for any existing Kubernetes cluster, and a warning plus notes in both pages tell readers to add `--gke`. The code blocks that omit it are logged in codefix_w7.md (fixes 1, 4, 8). Owner decision: fix the script so no flag means production, as `--help` says, or accept the doc change.) -- `installation.mdx`, `quick-start.mdx`: Kind installs with an empty `imageRegistry` (reason: `configure_image_registry()` exits for every non-OpenShift target when `global.imageRegistry` is empty, including `--kind`, but the package ships `imageRegistry: ""` and INTERNAL-README's Kind test sets only `frontendDomain`. Docs now say the check applies to every target except OpenShift; the owner should confirm what Kind users set.) -- `installation.mdx`: `--gke` flag (reason: verified. The argument parser accepts `--gke` (sets `GKE_DEPLOYMENT=true`, `ENVIRONMENT=production`), but `show_help` does not list it. Kept, with a note that `--help` omits it.) - -#### Removed or changed - -- `installation.mdx`: "35 services total", "Deployments (35 total)", "Infrastructure Services (10 services)" listing 11, "Services (26 total)", "Found 35 images", "Loaded 12 platform images", "~35 images" (reason: contradict each other and INTERNAL-README, which lists 18 Permit images plus 6 third-party images and 33 pods in a healthy cluster. All counts removed; the page lists services by group from INTERNAL-README and tells readers to run `kubectl get deployments,services,pvc`.) -- `installation.mdx`: `permit-foaz-proxy` and `permit-proxy` in the deployment and service lists (reason: not in INTERNAL-README's service list or healthy-pod list. Removed.) -- `installation.mdx`: "PostgreSQL ... Storage: 20GB persistent volume", `thirdPartyServices.postgres.persistence.size: "20Gi"`, `postgres-pvc ... 10Gi`, "OpenSearch 15GB (3 shards default)" vs `opensearch-pvc 20Gi`, "Redis 5GB" (reason: contradict each other and the package values in internal-side.sh: postgres 40Gi, redis 15Gi, opensearch 20Gi, rabbitmq 5Gi, keycloak 5Gi, read replica 5Gi. Sizes removed; the page points to `thirdPartyServices..persistence.size` and adds the verified expand-only PVC warning from internal-side.sh and INTERNAL-README.) -- `prerequisites.mdx`: storage table with growth rates and "Total Production Storage: 51GB minimum" (reason: sizes stale per internal-side.sh, growth rates unverifiable. Removed; page points to values.yaml.) -- `installation.mdx`: `imageRegistry: "" # Optional - Docker Hub if empty` (reason: contradicts configure_image_registry(), which exits for non-OpenShift targets when imageRegistry is empty. Removed; Step 4 now says pushing images to a registry is required except on OpenShift.) -- `installation.mdx`: "Policy Sync Issues (if configured)" and "permit-policy-sync-v2 ... Connects to your Git repository (if configured)" vs "Policy Sync configuration is mandatory" (reason: validate_frontend_domain() exits on CHANGEME_GIT_REPO_URL / CHANGEME_SSH_PRIVATE_KEY, and policy-sync-validation.yaml fails on empty values. Policy Sync is required; "if configured" removed, anchor kept.) -- `prerequisites.mdx`: "Git repository setup is mandatory" followed by "If you want to enable Git-based policy synchronization" (reason: same as above; optional wording removed.) -- `installation.mdx`: step timings "(1-2 minutes)", "(3-5 minutes)", "8-15 minutes"; `quick-start.mdx` description "5-10 minutes", body "10-15 minutes", "just a few minutes"; `landing.mdx` "Get running in 10-15 minutes"; push "10-20 minutes", "~12GB upload", "~12GB required in GAR" (reason: contradict each other and INTERNAL-README's ~6GB package; no source. Removed.) -- `installation.mdx`: "As of January 2026, the Helm chart includes built-in support for global.imagePullSecrets" (reason: dated wording. `imagePullSecrets` verified in the generated values.yaml; stated in present tense.) -- `installation.mdx`: "Pushes both the original tag and :latest tag to your registry" (reason: contradicts push-images-to-registry.sh, which pushes only `/:`. Rewritten.) -- `installation.mdx`: "For non-GKE registries ... manually update the imageRegistry field" (reason: contradicts push-images-to-registry.sh, which rewrites imageRegistry for any registry. Rewritten.) -- `installation.mdx`, `prerequisites.mdx`: "--gke ... Installs nginx-ingress-controller (if not present)", "The installer will set this up automatically with --gke flag", "Creates a Google Cloud Load Balancer automatically" (reason: contradicts install_ingress_controller(), which installs NGINX only for Kind. Prerequisites now say to install an ingress controller; the chart default `ingress.className: "nginx"` is verified.) -- `installation.mdx`, `prerequisites.mdx`: "Compatible with both GKE Standard and Autopilot" (reason: could not verify; the installer grants anyuid-style root containers on OpenShift and runs database containers as root, which Autopilot may restrict. Removed.) -- `installation.mdx`: "Error Handling and Recovery": "Automatically rolls back to previous state", "Cleans up partial image loads", "Reverts ingress changes", "Database connection - Retries every 30 seconds for 5 minutes", "Pod startup timeouts - Waits up to 10 minutes" (reason: not found in install-permit-platform.sh; retries exist only for docker load/push. Removed.) -- `installation.mdx`: "Network connectivity - Tests Docker registry access", "Storage requirements - Checks available disk space", "RBAC configuration - Sets up service accounts" in pre-install validation (reason: check_prerequisites() only checks tools and `kubectl cluster-info`. Removed; the run summary follows main().) -- `installation.mdx`: "Once generated, these passwords are stored in Kubernetes secrets and automatically reused" (reason: verified in generate_infrastructure_passwords() and INTERNAL-README. Kept in shorter form. Added verified fact that the passwords are written into values.yaml, with a warning.) -- `installation.mdx`: "Image Management ... Handles registry authentication (automatically for ECR)" (reason: not in the script. Removed.) -- `installation.mdx`: "The connection is still encrypted and secure for internal use" (reason: a self-signed certificate encrypts but does not authenticate the server; "secure" is unqualified. Reworded.) -- `installation.mdx`: "Infrastructure Requirements by Target" (Requires docker for production K8s) (reason: check_prerequisites() requires only kubectl and helm for production and oc/kubectl/helm for OpenShift; docker is needed for Kind and for the push script. Moved to prerequisites with corrected tool lists.) -- `prerequisites.mdx`: "Current Deployment Resource Usage" (~1.2 cores, ~13GB RAM, 51GB, 26 internal services, "8 OPAL relay services", "Keycloak ~1.5GB, OpenSearch ~3.7GB", "permit-data-generator: 500m CPU each") and "Service Categories (35 total services)" (reason: unverifiable snapshot numbers that contradict INTERNAL-README counts. Removed.) -- `prerequisites.mdx`: "Why This Complexity?" bullets ("Sub-millisecond policy decisions with distributed caching", "Supports millions of authorization requests per day", "Multi-tenancy", "SCIM integration, webhooks, advanced analytics") (reason: marketing, not prerequisites; performance figures are about PDPs, not the control plane install. Removed.) -- `prerequisites.mdx`: "Small teams (50-500 users)", "Large organizations (1000+ users)" (reason: no source. Removed.) -- `prerequisites.mdx`: "Multi-Node Cluster (3-4 nodes)" vs table "4+ nodes" (reason: internal contradiction; kept "4 or more" to match the table and the OpenShift section.) -- `prerequisites.mdx`: "Version: OpenShift 4.10+ on AWS" vs "OCP 4.8+" and "Red Hat OpenShift: 4.8+" (reason: internal contradiction; kept 4.8, which appears three times. Version minimums are not checked by the installer and remain unverified.) -- `prerequisites.mdx`: GKE node type "n1-standard-4 or e2-standard-4" vs "e2-standard-8 (8 vCPU, 32GB) or larger" (reason: internal contradiction; replaced with a node-type table mapped to the two node sizes in the sizing table. Instance specs are public provider facts. `Standard_D4s_v3` added as the 4 vCPU/16 GB Azure equivalent.) -- `prerequisites.mdx`: `3128 Proxy Services`, "Database connections (3 instances)", "15+ internal API services" (reason: proxy not in INTERNAL-README; counts unverified. Removed.) -- `prerequisites.mdx`: "Expected Outputs" blocks with check marks (reason: not real command output. Removed; prose states the real expected results of `kubectl auth can-i` and `oc auth can-i`.) -- `prerequisites.mdx`: Google Container Registry (legacy) block and duplicate Artifact Registry creation block (reason: registry creation is owned by installation Step 4; GCR is Google's deprecated product. Removed.) -- `prerequisites.mdx`: duplicate OpenShift and Kubernetes validation blocks under "Cluster Access Requirements" (reason: repeated under "Pre-Installation Validation"; one copy kept.) -- `prerequisites.mdx`: TLS section with `--generate-tls`, custom certificate YAML, and `--skip-tls-check` blocks (reason: duplicates installation.mdx, which owns TLS. Replaced with a decision list and link.) -- `prerequisites.mdx`: "The installer is designed to be self-contained and handles most setup automatically" (reason: vague; replaced with a requirements table.) -- `prerequisites.mdx`: "Without write access ..." rationale for deploy-key write access (reason: write access kept from the original; the reason Policy Sync needs it was not traced in source.) -- `landing.mdx`: "Encryption at Rest - PostgreSQL data encryption for policies and configurations", "Audit Logging - Complete decision logs", "enterprise-grade security", "Enhanced security", "RBAC & IAM - Role-based access control via integrated Keycloak" (reason: no source for encryption at rest; hype. Replaced with a table of controls verified in the installer: TLS options, generated credentials, Keycloak sign-in, SSH deploy key, PDP API key, namespace.) -- `landing.mdx`: "Backend Services ... (~20+ microservices)" (reason: contradicts counts elsewhere. Removed.) -- `landing.mdx`: "Air-gapped installation - No internet connection required post-setup", "High availability - Multiple replicas for critical services" (reason: air-gapped verified by image tars in the package (INTERNAL-README), kept; note that on Kind the NGINX ingress images are downloaded separately. HA replicas not verified; removed.) -- `landing.mdx`, `installation.mdx`: added verified warning that OpenSearch Dashboards at `/opensearch/` has no authentication (source: installer completion output "no authentication required"). -- `quick-start.mdx`: added step "Push the images to your registry" as required for non-OpenShift targets (source: configure_image_registry()). -- `quick-start.mdx`: added danger admonition that `kubectl delete namespace permit-platform` deletes the PVCs (Kubernetes behavior; data loss depends on reclaim policy). - -#### Code blocks removed (duplicates, illustrations of internals, or fabricated output) - -installation.mdx: pseudo "Script commands" (grep/which), image list, `openssl rand -hex 16` secret generation (script uses `openssl rand -base64`), `alembic upgrade head` migration commands, service discovery map, "Configuration Files the Script Uses" values block, `kubectl get deployments/services/secrets/pvc` sample outputs, "Detailed Logging" sample, `docker pull .../hello-world || echo "Authentication configured"` (always prints success), per-flag "What it does" blocks for default/OpenShift/GKE/Kind/generate-tls/skip-tls-check/skip-openshift-registry/namespace/dry-run/skip-images (replaced by verified tables; the GKE and default blocks had wrong comments), stale `--help` output (missing `--yes`), fabricated "Installation Output" log, frontend URL block, scaling and storage blocks (owned by management.mdx). -quick-start.mdx: `kubectl create secret docker-registry` block (owned by installation.mdx, linked). -prerequisites.mdx: listed above. - -### Batch u8 (`permit-mcp-gateway/advanced-features.mdx` and related pages) - -#### Removed internal admonition (advanced-features.mdx) -- `docs/permit-mcp-gateway/advanced-features.mdx`: removed the published internal admonition "Items flagged on the marketing site but not yet detailed in documentation". Each item it listed, for owner review: - - `docs/permit-mcp-gateway/advanced-features.mdx`: "Sub-millisecond authorization decisions" for the gateway (reason: not owner-confirmed for the gateway; the confirmed sub-millisecond figure is for the PDP and the page did not tie it to the PDP; the marketing enterprise page says "High-performance PDP, sub-10ms"). Removed. - - `docs/permit-mcp-gateway/advanced-features.mdx`: "Anomaly detection ... under development as part of session monitoring" (reason: roadmap, could not verify). Removed. - - `docs/permit-mcp-gateway/advanced-features.mdx`: "Shadow agent detection ... an area of active research" (reason: roadmap, could not verify; the marketing site lists "IGA / PAM Connectors for Shadow MCP"). Removed. - -#### Availability and maturity (advanced-features.mdx) -- `docs/permit-mcp-gateway/advanced-features.mdx`: "Agent Interrogation is under active development ... being refined", and the Maturity notes for Agent Verification, Session Monitoring, and Intent-Based Access Control ("early access", "active development", "emerging", "roadmap") (reason: roadmap/dated wording, could not verify). Replaced with "Contact Permit" in the availability table (anchor `#feature-maturity-summary` kept). -- `docs/permit-mcp-gateway/advanced-features.mdx`: Enterprise-plan status of Agent Interrogation, Agent Verification, Session Monitoring, Permission Receipts, Intent-Based Access Control (reason: could not verify; permit.io/mcp-gateway/pricing lists only HITL approvals and configurable consent windows as Enterprise). HITL and Time-Limited Consent Enterprise status verified there. -- `docs/permit-mcp-gateway/advanced-features.mdx`: behavior kept but unverified against source: the three parts of the composite identity, drift-triggered reactions (downgrade trust, re-consent, block, approval), step-up consent, declared-intent logging, drift history, per-workflow policy, exportable permission receipts, session monitoring intent comparison (reason: could not verify; gateway source search hit the GitHub rate limit; only `identify_self`, fingerprinting, and drift monitoring are confirmed on the marketing site and in the egress proxy security page). Owner to confirm these ship. -- `docs/permit-mcp-gateway/advanced-features.mdx`: Calendly links replaced with https://www.permit.io/demo; "Contact us" mailto links in maturity notes removed. - -#### Cross-page conflicts (not resolved) -- `docs/permit-mcp-gateway/managing-humans-and-agents.mdx`: "The same person using multiple MCP clients creates separate agent identities" vs "if both Alice and Bob use Cursor ... the same Cursor agent identity may have roles on both user_profile:alice and user_profile:bob" (reason: page contradicts itself; architecture.mdx shows each client gets a `client_id` via dynamic client registration and sessions keyed by client_id + subject, but no page says whether two humans' Cursor installs share a client_id). Admonition reworded to "If the same agent identity is authorized by two humans, it holds a role on each profile", without claiming two Cursor installs share one identity. Owner to confirm. -- `docs/permit-mcp-gateway/platform.mdx`: "Revoking access terminates any active sessions for that user on the affected MCP server" (reason: contradicts managing-humans-and-agents.mdx "removes the profile-to-server relation"; consent-service.mdx says revocation "immediately invalidates the session"). Both pages now say only that the agents' next tool call to that server is denied; managing-humans keeps the relation-removal mechanism, which matches permit-integration.mdx. Owner to confirm whether sessions are also terminated. -- `docs/permit-mcp-gateway/demos/n8n-linear-mcp-gateway.mdx`: "you will be asked to import and assign trust levels for all of Linear's tools" (reason: contradicts consent-service.mdx, which describes a single trust level slider with Allowed/Denied badges). Reworded to "shows Linear's tools with their trust levels, and you set the trust granted to the n8n workflow" with a link to Consent Service. Screenshot tool-import.png kept; owner should check it matches the consent screen. -- `docs/permit-mcp-gateway/demos/n8n-linear-mcp-gateway.mdx`: "go to the Permit MCP Gateway dashboard and toggle the trust level" (reason: location unspecified; now links to Modifying agent trust levels on the Agents page, an inference from managing-humans-and-agents.mdx). Owner to confirm the screenshots show that page. -- `docs/permit-mcp-gateway/demos/linear-mcp-gateway.mdx`: "restricting a Project Manager to read-only access" (reason: contradicts steps, which give the PM Medium trust and list_issues set to Medium). Description aligned with the steps. The click path "Dashboard > Hosts > Create Host" differs from host-setup "Dashboard > Create Host"; kept to match the screenshot. -- `docs/permit-mcp-gateway/host-setup.mdx`: Cursor and Claude Desktop snippets use `npx mcp-remote` while quickstart.mdx uses a `url` key (reason: cross-page conflict from the audit; quickstart is not assigned to this batch). host-setup now explains mcp-remote, matching guide.mdx. - -#### Removed or reworded claims -- `docs/permit-mcp-gateway/host-setup.mdx`: "You can evaluate with the hosted gateway and migrate seamlessly when ready" (reason: "seamlessly" unverifiable). Kept "You can evaluate with the hosted gateway first." -- `docs/permit-mcp-gateway/host-setup.mdx`: rollout phase durations ("1–2 weeks", "2–4 weeks") kept but labeled as suggestions (reason: guidance, not product fact). -- `docs/permit-mcp-gateway/human-in-the-loop.mdx`: Calendly "Schedule a demo" link replaced with https://www.permit.io/demo. -- `docs/permit-mcp-gateway/human-in-the-loop.mdx`: keyboard shortcuts, card border colors, "Extend +5 min" in the last 60 seconds, preset rejection reasons (reason: could not verify against source due to the GitHub rate limit; kept as volatile UI facts). - -#### Media removed (duplicates; the owning page keeps them) -- `docs/permit-mcp-gateway/platform.mdx`: create-host.png, create-host-environment.png, import-mcp-connect.png, import-mcp-review.png (reason: host creation and import procedures moved to host-setup.mdx, which keeps the same screenshots). -- `docs/permit-mcp-gateway/host-setup.mdx`: human-detail.png in the grant-access step (reason: granting access now links to managing-humans-and-agents.mdx, which keeps the screenshot). - -### Batch w8 (`how-to/deploy` and related pages) - -Sources used for verification: permitio/permit-deployments `on-prem/scripts/install-permit-platform.sh` and `on-prem/charts/permit-platform/templates/*` (copies in `scratchpad/w8src/`), permitio/PDP `charts/pdp/{values.yaml,templates/*}` and `pdp-server/src/opa_client/allowed.rs`. The chart's `values.yaml` isn't in permitio/permit-deployments (404), so default values can't be verified. - -#### Resolved conflicts - -- Admin password secret: the installer reads `global-infrastructure-secret` key `KEYCLOAK_ADMIN_PASSWORD` first and falls back to `keycloak-admin-secret` key `password` (install.sh lines 257-265). management.mdx and troubleshooting.mdx now say this; troubleshooting code blocks still read `keycloak-admin-secret` (code fix logged). -- `global.postgres` vs `thirdPartyServices.postgres`: both are real. `global.postgres` feeds connection strings (global-infrastructure-secret.yaml); `thirdPartyServices.postgres` configures the deployment (persistence.size, config). Explained in reference.mdx. -- `ingress.tls.certificateFiles`: verified (tls-secret.yaml reads certFile/keyFile via `.Files.Get`). Inline `certificate.cert/key` are written raw into `data` (must be base64). Documented in reference.mdx. -- `backup`/`restore` (`s3://` storageLocation), `autoscaling`, `pgBouncer`, `monitoring`, `networkPolicy`, `resourceQuota`, top-level `securityContext.runAsNonRoot`, `migrations.runOnInstall/runOnUpgrade`: no chart template reads them. reference.mdx now says they have no effect (code blocks kept; removal logged in codefix_w8.md). -- Duplicate "Configuration Management" H2s in management.mdx: resolved; second one is H3 "Inspect the running configuration" with id `configuration-management-1`. -- Uninstall and support bundle blocks moved byte-identical from reference.mdx to management.mdx (codeguard reports them as moved across files); reference.mdx links to the owner sections. - -#### Removed or unverified claims - -- `docs/how-to/deploy/on-prem/change-organization-tier.mdx`: "As of the latest version, the on-premise installer automatically sets all organizations to Enterprise tier" (reason: undated; replaced with the verified migrations-job behavior and its log lines from migrations.yaml). -- `docs/how-to/deploy/on-prem/change-organization-tier.mdx`: Before/After UI strings "PRO" badge and "14 days left in Pro Trial" (reason: could not verify frontend strings). -- `docs/how-to/deploy/on-prem/change-organization-tier.mdx`: "`billing_tier` controls ... Upgrade prompts" (reason: could not verify). -- `docs/how-to/deploy/on-prem/troubleshooting.mdx`: "Our support team has experience with all major Kubernetes platforms and can assist with advanced troubleshooting scenarios" (reason: marketing, unverifiable). -- `docs/how-to/deploy/on-prem/management.mdx`, `troubleshooting.mdx`, `reference.mdx`: "35 Permit services" / "(all 35 Permit services)" in code comments kept byte-identical; prose no longer states a count (reason: could not verify count; installation page used other figures). -- `docs/how-to/deploy/on-prem/reference.mdx`: storage sizes "10Gi Minimum, 20Gi+ for production" (postgres), "15Gi Minimum for 3 shards" (opensearch), and image tags `opal-server 0.7.5-rc.7`, `keycloak 20.0.5`, `opensearch 2.11.0`, `postgres_15-alpine`, `rabbitmq_3.12.10` (reason: chart values.yaml not available to verify; kept inside code blocks as examples, prose says the package's values.yaml is the source of truth). management.mdx 50Gi/100Gi are labeled as examples. -- `docs/how-to/deploy/on-prem/reference.mdx`: `thirdPartyServices.keycloak.persistence.size` and `persistence.storageClass` (reason: not read; keycloak-postgres-pvc is fixed at 5Gi and no template sets storageClassName). Prose now says so. -- `docs/how-to/deploy/on-prem/reference.mdx`: `global.opensearch`, `global.keycloak.realm/clientId/clientSecret`, `permitServices.policySync.branch/syncInterval`, `permitServices.backend.env.LOG_LEVEL/ENABLE_MONITORING` (reason: not read by templates). Prose now says so. -- `docs/how-to/deploy/on-prem/management.mdx`, `troubleshooting.mdx`: `policy-sync-ssh-key` and `postgres-secret` secrets (reason: neither the chart nor the installer creates them; policy sync gets the key as the `POLICY_REPO_AUTH_PRIVATE_KEY` env var). Prose now says so. -- `docs/how-to/deploy/on-prem/management.mdx`: "Or register a new account" in the sign-in code block (reason: could not verify self-registration is enabled in the Keycloak realm; kept in code block). -- `docs/how-to/deploy/on-prem/management.mdx`: health URLs `/health`, `/scim/health`, `/api/v2/health` and backend `:8000/health` (reason: not verified against service routes; kept as in original). -- `docs/how-to/deploy/on-prem/pdp-deployment.mdx`: `PDP_LOG_LEVEL=DEBUG` env var example (reason: not found in permitio/PDP; prose points to `pdp.debug_mode=true`, which sets `PDP_DEBUG`, verified in charts/pdp/templates/deployment.yaml). -- `docs/how-to/deploy/on-prem/pdp-deployment.mdx`: "Look for successful connection messages to the control plane" (reason: exact log text not verified; replaced with a generic instruction to look for control plane or API key errors). - -### Batch w9 (`permit-mcp-gateway/architecture.mdx` and related pages) - -Source checked: internal repo permitio/agent-security (gateway/src, packages/policy-management, helm/agent-security, on-prem/CUSTOMER-README.md, helm/agent-security/examples/values-onprem.yaml) and permitio/PDP charts/pdp. - -- `docs/permit-mcp-gateway/architecture.mdx`: "Permit MCP Gateway is available as a hosted gateway deployment" / Integration Patterns table with only "Hosted Gateway" (reason: contradicts enterprise-deployment.mdx and on-prem-installation.mdx; replaced with a three-model component table linking to enterprise-deployment#deployment-models) -- `docs/permit-mcp-gateway/architecture.mdx`: Data Flow mermaid diagram and protocol table with ports 8001, 8002, 3000, 8080, 6379, 5432 and "AWS ALB (TLS termination)" (reason: internal, hosted-infrastructure specific, volatile, not actionable for operators; replaced with a port-free "what moves" table; the mermaid code block was removed) -- `docs/permit-mcp-gateway/architecture.mdx`: rate-limit table "/api/auth/sign-in 100 req / 5 min, /api/auth/sign-up 100 req / 10 min, /oauth/register 100 req/min, /mcp 1000 req/min, writes 1200 req/min, all traffic 2000 req/min" (reason: could not verify; consent-service/src/app/api/oauth/register/route.ts says production limits are enforced by AWS WAF at the edge, which is not in the repo; volatile. Kept the per-IP behavior, the 429 JSON body (shape confirmed in platform/src/lib/permit/client.ts), and the NAT/support note) -- `docs/permit-mcp-gateway/architecture.mdx`: env var table `GATEWAY_JWT_TTL_SECONDS` (default 300, 60-3600) and `GATEWAY_JWT_REQUIRE_VAULT` (reason: verified in gateway/src/config.rs but not settable on the hosted gateway, and the on-prem Helm chart exposes the vault flag under a different key and does not wire the KMS vault (helm/agent-security/values.yaml comments); removed as internal. Default 5-minute lifetime kept) -- `docs/permit-mcp-gateway/architecture.mdx`: "When the token vault is enabled (`VAULT_ENABLED=true` + `AWS_KMS_KEY_ID`), the key is encrypted at rest using AES-256-GCM with AWS KMS envelope encryption; without vault it is stored as plaintext JSON" (reason: internal env vars and a storage detail the on-prem chart does not wire; removed) -- `docs/permit-mcp-gateway/architecture.mdx`: rotation procedure `redis-cli DEL gateway:jwt:signing_key` then `kubectl rollout restart deployment/gateway` (reason: deployment name is wrong for the on-prem chart (`agent-security-gateway`) and the step is not actionable for hosted customers; bash block removed, page now says contact your Permit team. 90-day warning, metric name `gateway_jwt_signing_key_age_seconds`, and kid behavior kept, verified in gateway/src/clients/gateway_jwt.rs and gateway/src/metrics.rs) -- `docs/permit-mcp-gateway/architecture.mdx`: "under 10 lines of meaningful code" (reason: filler; removed) -- `docs/permit-mcp-gateway/architecture.mdx`: "Adopting the gateway requires a single configuration change" and "Key Advantages" / "full power of Permit's policy engine" / "permissions-as-a-service" lists (reason: marketing, duplicated overview; removed) -- `docs/permit-mcp-gateway/architecture.mdx`: trust-level keyword lists (reason: kept, verified in packages/policy-management/src/heuristics/tool-trust.ts; clarified they are suggestions an admin can override and that high patterns are checked first) -- `docs/permit-mcp-gateway/architecture.mdx`: added "sends Cache-Control: public, max-age=300" (verified in gateway/src/routes/public/well_known/gateway_jwks.rs), MCP error -32004 (gateway/src/routes/public/mcp/errors.rs), list_tools returns all upstream tools and Agent Interrogation / HITL checks run in the call_tool chain (gateway/src/routes/public/mcp/handler.rs) -- `docs/permit-mcp-gateway/architecture.mdx`: customer-controlled model: whether the admin dashboard runs in the customer network (reason: could not verify; table says "Contact Permit for your deployment") -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Permit does not claim certification under specific compliance frameworks" (reason: contradicts owner-confirmed claims; replaced with "Permit.io is HIPAA compliant and SOC 2 Type II attested") -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Permit offers two enterprise deployment models" vs "supports three deployment models" (reason: internal contradiction; page now lists three models: hosted, customer-controlled, fully on-premises) -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "set up a hosted gateway in under 5 minutes" (reason: unverified number; removed) -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Schedule a demo" link to calendly.com/permit-io/demo (reason: style guide; changed to https://www.permit.io/demo) -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Agent Verification (early access)", "Session Monitoring (early access)", "Intent-Based Access Control (roadmap)" (reason: roadmap/dated wording and conflicts with advanced-features availability table ("Contact Permit"); replaced with a table that links to that availability table) -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Audit logs: Your infrastructure + Permit.io (configurable)" and "Policies and users can be migrated between deployment models" for customer-controlled (reason: kept from original, could not verify in source; owner should confirm) -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "you can migrate to customer-controlled deployment at any time" (reason: "at any time" unverifiable; softened to "Permit can help you move ... later") -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Resilience: authorization continues even if internet connectivity to Permit.io is temporarily interrupted" (reason: kept, reworded to the mechanism: the PDP keeps its last synced policy; behavior of OPAL-backed PDPs, not measured for the gateway) -- `docs/permit-mcp-gateway/enterprise-deployment.mdx`: "Join our Slack ... talk with ... other enterprise users" (reason: unverifiable audience claim; now "Ask questions in the Permit Slack community") -- `docs/permit-mcp-gateway/on-prem-installation.mdx`: "You should see 10 pods" with 2/2/2/2/1/1 (reason: kept, verified against helm/agent-security/examples/values-onprem.yaml (the installer's values.yaml per on-prem/internal-side.sh); now scoped to "the default on-premises values template") -- `docs/permit-mcp-gateway/on-prem-installation.mdx`: "Verify the gateway health endpoint" with `curl https://app.../api/health` (reason: the endpoint is the admin dashboard (platform) liveness route, platform/src/app/api/health/route.ts, not the gateway; prose relabeled, code unchanged) -- `docs/permit-mcp-gateway/on-prem-installation.mdx`: "Permit environment API key from the Permit Platform dashboard (Settings → API Keys)" (reason: UI path not verified for the self-hosted Permit Platform; replaced with a link to /overview/get-api-key) -- `docs/permit-mcp-gateway/on-prem-installation.mdx`: "Some DNS providers do not resolve wildcard records for their own apex" (reason: technically imprecise explanation; kept only the actionable check for an explicit app record) -- `docs/permit-mcp-gateway/on-prem-installation.mdx`: PDP service `permitio-pdp` on port 7766 (reason: kept and stated, verified in permitio/PDP charts/pdp/templates/service.yaml and values.yaml) - -### Batch u9 (`api/working-with-abac` and related pages) - -- `docs/api/working-with-abac/overview.mdx`: "we can now define Condition Set Rules that will be part of Condition Sets" (reason: contradicts the API spec; condition set rules are a separate object under `/v2/facts/{proj_id}/{env_id}/set_rules` that reference sets by key). Replaced with the correct relationship. -- `docs/api/working-with-abac/overview.mdx`: "Previously, you had to make a separate API call to get this information, however, currently with the new version of the API, you can directly pass in the verbose versions" (reason: dated wording; replaced with the spec fact that `proj_id`/`env_id` accept an ID or a key). -- `docs/api/working-with-abac/building-conditions.mdx`: "This example is invalid because we specify the user.age to be between 15 and 18, but then set another condition to test for the age being greater than 48. This will throw an Unbound Error." (reason: contradicts source; `{"or": [{"user.age": ...}, {"user.age": ...}]}` validates as `OperatorOr[BooleanExpression]` of `AttributeCondition`s in permit-backend `schemas/conditions.py`; the prose said 48 while the code says 40). The section is relabeled as a valid same-attribute example; anchor `#invalid-1` kept. -- `docs/api/working-with-abac/building-conditions.mdx`: "not" example "A user with the Editor role can only request changed to the document ... will be reflected as: An Editor can request changes to the document and any other available resources." (reason: incoherent, does not describe logical negation). Replaced with a plain negation example. -- `docs/api/working-with-abac/building-conditions.mdx` (risk to confirm, samples kept): the examples use `subject.*` and `environment.*` attribute prefixes. `ConditionsBlockSchema` accepts them (`AttributeObjectType` includes subject and environment), but `ConditionSet._sanitize_condition` in permit-backend `schemas/condition_set.py` only accepts `user.`, `resource.`, `tenant.`, `context.`, and `role.` and raises "Invalid comparison key" otherwise during policy generation. A condition set saved with `subject.paying` or `environment.location` may fail when the policy is generated. Owner should confirm and consider switching the samples to `user.` / `context.`. -- `docs/api/working-with-abac/condition-sets.mdx`: "There are currently two types of condition sets" (reason: dated wording; "currently" removed, the two types are the spec enum `userset`/`resourceset`). -- `docs/api/working-with-abac/operators.mdx`: "For example, if you want to check if the user's email is equal to the user's first name, you can use the following condition" (reason: contradicts the sample, which uses `contains`). Prose now says "contains". -- `docs/api/working-with-abac/operators.mdx`: "There are currently three types of logical operators" (reason: dated wording). Also added the operators `in`, `between`, `match`, `array_len_equals`, `array_len_greater_than`, `array_len_less_than`, which exist in `ComparisonOperatorType` (permit-backend `schemas/operators/comparison.py`) but were missing from the table. -- `docs/api/rbac/rbac-example.mdx`: "RBAC API\" and delete it below." and the duplicated H4 "We have a shared todo app..." (reason: editing residue; removed, anchor not linked anywhere). -- `docs/api/rbac/disable-rebac-to-increase-performance.mdx`: "The updated configuration will take effect only when a new PDP instance is started" (reason: could not verify in permit-backend or PDP; `rebac_disabled` is read by the policy synchronizer `env_updater.py` when the policy is generated, but the source does not show whether running PDPs pick it up without a restart). Kept "restart running PDPs" as a step without the "only when" claim. Owner should confirm. -- `docs/api/rbac/disable-rebac-to-increase-performance.mdx` (unverified, kept): `rebac_disabled` is not in the OpenAPI spec (`EnvironmentUpdate.settings` is an untyped object). The key is confirmed in permit-backend `policy_synchronizer/.../env_updater.py` (`(env.settings or {}).get("rebac_disabled", False)`). -- `docs/api/elements/overview.mdx`: "The API now allows us to create Embeddable Element calls, which give much more flexibility when defining them." (reason: dated, vague). Removed. -- `docs/api/elements/access-request-api.mdx`: "Please note that the `elements_config_id` refers to the ID of the user management element that is linked to the access request element." (reason: could not verify; the spec describes `elements_config_id` only as the ID or key of an elements config). Page now says "the ID or key of the element configuration". Owner should confirm which element config ID the facts-path endpoints expect. -- `docs/api/elements/access-request-api.mdx` and `access-requests.mdx`: "You can filter access requests by passing the following headers" (reason: contradicts the spec; filters are query parameters, and the facts-path list endpoint has no `tenant` filter while the elements-path one does). -- `docs/api/elements/access-requests.mdx`, `operation_approval.mdx`: "Remember to copy your `SDK Secret Key`" and "Get your API_SECRET_KEY ... Replace API_SECRET_KEY" (reason: glossary term is "API key"; the element-session curls authenticate with the login cookie, not the API key). The API key is now described only as the SDK constructor credential. -- `docs/api/elements/operation_approval.mdx`: Redoc link "Approval Flow API in the Permit Redoc" pointed to `#tag/Access-Requests` (reason: wrong tag). Now `#tag/Operation-Approval-(EAP)`. -- `docs/api/elements/access-requests.mdx`, `operation_approval.mdx` (unverified, kept from the original pages and consistent with `docs/embeddable-uis/element-login.mdx`): `USER_NOT_FOUND` when the user is not in the tenant; one tenant per session; the requesting user must belong to the tenant; non-reviewers see only their own requests; the ticket `redirect_url` is a `get_cookie` URL. -- `docs/updates-and-feedback/changelog.mdx`: "Explore the evolving journey of our permissions and access control features" (reason: hype). The Canny changelog responds 200, but its most recent entry is dated 2025-02-20 (from the page's og:image version and entry dates). A Productlane changelog also exists at https://permit.productlane.com/changelog (200, "Permit.io Changelog | Productlane", entries render client-side). The link was kept on Canny; owner should decide whether the changelog moved to Productlane. -- `docs/updates-and-feedback/feature-requests.mdx`: "guiding the next wave of features we introduce at Permit.io" (reason: marketing). Link https://permitio.canny.io/feature-requests responds 200 (Canny board, 174 posts at check time). -- `docs/updates-and-feedback/roadmap.mdx`: "Get a glimpse into the future of access control ... innovations" (reason: hype). Link https://permit.productlane.com/roadmap responds 308 to /request (200, "Permit.io feature requests | Productlane", shows In Progress and Completed ideas). Not dead, but the roadmap and feature requests now live on two different hosts (Productlane and Canny). Owner should decide whether feature requests should also point to Productlane `/request`. - -### Batch u10 (`authentication/permit-and-authentication.mdx` and related pages) - -- `docs/authentication/permit-and-authentication.mdx`: "Compatible with All Authentication Standards: OAuth 2.0, OpenID Connect (OIDC), SAML, WS-Fed, Headers, mTLS" (reason: could not verify; Permit SDK checks take a user key, the app verifies tokens. WS-Fed and mTLS support not documented anywhere) -- `docs/authentication/permit-and-authentication.mdx`: "Permit.io's authorization layer will integrate with it through our flexible handoff mechanisms" / "integrate seamlessly with any authentication solution" (reason: marketing; replaced with mechanism description) -- `docs/authentication/permit-and-authentication.mdx`: IdP-managed roles have "no support for ReBAC" (reason: could not verify; SCIM and handoff code can write any role assignment. Replaced with tradeoff about runtime-granted roles) -- `docs/authentication/permit-and-authentication.mdx`: "Permit.io ensures your AuthZ policies remain accurate and up-to-date" (reason: unverifiable guarantee) -- `docs/authentication/permit-and-authentication.mdx`: removed "Why This Works" section (authoring notes) and "Book a Demo" link to io.permit.io/docs-to-call (non-standard demo link) -- `docs/authentication/your-authentication.mdx`: "Permit.io measures usage through Monthly Active Users (MAUs) ... counted as a single MAU" (reason: pricing/billing detail, volatile, not an authentication how-to; owner should confirm it lives on a pricing page) -- `docs/authentication/your-authentication.mdx`: "specific endpoint and method will be detailed in the API documentation" (stale meta text; replaced with the verified endpoint `POST /v2/facts/{proj_id}/{env_id}/bulk/users` from the OpenAPI spec) -- `docs/authentication/fusionauth.mdx`: "Guide coming soon!" and description "integration guide is coming soon" (reason: roadmap claim) -- `docs/authentication/fusionauth.mdx`: "Clone and play with our demo NextJS project" (reason: contradicts repo; filipermit/permit-x-fusionauth is an Express server plus a webpack React client, not Next.js) -- `docs/authentication/fusionauth.mdx`: tracking link `https://fusionauth.link/4fS8uTU` replaced with `https://fusionauth.io` (reason: tracking redirect) -- `docs/authentication/fusionauth.mdx`, `docs/authentication/supertokens.mdx`: OWNER REVIEW. Both link to personal repos `https://github.com/filipermit/permit-x-fusionauth` (last commit 2022-09-20) and `https://github.com/filipermit/permit-x-supertokens` (last commit 2022-08-24). Both exist (gh api returns 200), so links kept. Both pin `permitio` SDK 0.0.5 and use `permit.write()` and `roles` in `syncUser()`, which the current SDK doesn't have; pages now say so. Consider moving to the permitio org or archiving. -- `docs/authentication/fusionauth.mdx`: SECURITY, OWNER REVIEW. filipermit/permit-x-fusionauth commits a Permit API token (JWT, exp 2023-09) in `server/routes/permit.js` and `server/routes/sync-user.js`, and a FusionAuth client secret and API key in `config.js`. Page now warns readers to replace them; owner should confirm those credentials are revoked. -- `docs/authentication/supertokens.mdx`: "Enjoy the demo!" and emoji headings removed (style). Verification steps added from repo source (log line text, roles `Friend`/`Stranger`, tenant `SuperTokens`, resource `card`); the app was not run. -- `docs/authentication/hankopermit.mdx`: "Permit is the leading authorization platform for developers" (reason: unverifiable marketing claim) -- `docs/authentication/hankopermit.mdx`: ABAC steps "This new user should not be able to delete tasks" then "You should also be able to delete it" (reason: contradictory; rewritten to match the configured policy and repo article.md: second user can't delete first user's note, can delete own note, admin can delete any note) -- `docs/authentication/hankopermit.mdx`: "limited to the same user who created the role" (reason: wrong, should be the note's owner) -- `docs/authentication/hankopermit.mdx`: step "copy the API URL" reused screenshot 3.jpg (project creation); replaced with existing static/ui-videos/integrations/authentication/hankopermit/4.jpg, which shows the API URL settings (media swap, same folder) -- `docs/authentication/hankopermit.mdx`: screenshot 13.jpg shows `post` unchecked on `notes` for both roles and all actions on `Owned Notes`; step text follows the RBAC policy from 8.jpg. Minor mismatch, owner may retake. -- `docs/authentication/logto.mdx`: "Seamless user authentication", "easily adapt your security model ... without changing your code" (reason: filler/marketing) -- `docs/authentication/logto.mdx`: Slack link io.permit.io/docs-to-slack changed to io.permit.io/slack (house standard) -- `docs/authentication/logto.mdx`: added warnings that the check-permission route trusts a `userId` query parameter and that the webhook route doesn't verify Logto's signature. "Logto signs webhook requests with the webhook's signing key" is from Logto's webhook docs (not re-fetched this session); owner may confirm. -- `docs/authentication/auth0/permit-integration.mdx`: "Auth0 is one of the leading authentication platforms ... Permit.io is the leading authorization platform" (reason: unverifiable marketing) -- `docs/authentication/auth0/permit-integration.mdx`: link `http://localhost:3000/integrations/authentication/auth0-demo` (reason: broken localhost link; replaced with `/authentication/auth0/auth0-demo-app#41-sync-auth0-with-permit`) -- `docs/authentication/auth0/permit-integration.mdx`: "delete tasks immediately" (kept as "without signing out and in again"; propagation time unverified) -- `docs/authentication/auth0/auth0-demo-app.mdx`: removed the duplicated Auth0 Action steps, Action code block, and session object block; page links to the owner page `/authentication/auth0/permit-integration#31-sync-auth0-with-permit` (codeguard reports these two blocks missing: intentional dedupe per coordinator note) -- `docs/authentication/auth0/auth0-demo-app.mdx`: "the `userProvider` in `_app.tsx` redirects the user to the login page if they have not logged in" (reason: could not verify; UserProvider only provides user context) -- `docs/authentication/auth0/auth0-sync-script.mdx`: "Auth0 is one of the leading authentication platform ... Permit.io is the leading authorization platform" (reason: marketing) -- `docs/authentication/auth0/auth0-sync-script.mdx`: link `/sdk/python/quickstart_python_sync#1-get-your-permit-environment-api-key` replaced with `/overview/get-api-key` (fragile partial anchor, per cross-page finding) -- `docs/authentication/auth0/auth0-sync-script.mdx`: added from script source: after creating missing roles the script exits without syncing users (must rerun); tenant prompt defaults to `default` -- `docs/authentication/cognito/cognito-demo-app.mdx`: added a warning that the repo's `/api/sync` route throws ReferenceError (payload out of scope) so users aren't synced; workaround is adding the user in Directory. Owner should fix permitio/cognito-integration. -- `docs/authentication/cognito/cognito-demo-app.mdx`: repo README says run the frontend with `npm install` and serve on port 8000; the frontend has no package.json and the backend listens on 8000 with CORS for 8181. Page says serve frontend on 8181. Owner should fix README. -- `docs/authentication/cognito/permit-integration.mdx`: "Using Cognito and Permit together allows you to easily manage ... in a secure and scalable way", "it will take effect immediately without refresh" (reason: marketing / unverified timing) -- `docs/authentication/cognito/permit-integration.mdx`: "For production use container / sidecar PDP" linked to the Node.js quickstart (reason: wrong target; now links to `/how-to/deploy/deploy-to-production`) -- `docs/authentication/stytch/permit-integration.mdx`: "Stytch is one of the leading authentication platforms ... robust and scalable", "Permit.io is a leading authorization platform" (reason: marketing) -- `docs/authentication/stytch/permit-integration.mdx`: "Adding a user to the Tenant" via `syncUser` (reason: wrong; syncUser doesn't place a user in a tenant, role assignment does. Heading renamed with old anchor kept) -- `docs/authentication/stytch/permit-integration.mdx`: removed the second copy of the account-owner-role.png screenshot (duplicate of the first on the same page) -- `docs/authentication/stytch/permit-integration.mdx`: OWNER REVIEW. user-synced.png breadcrumb shows project "Barclays Planning" (a real company name) and a personal avatar; style guide asks for fictional companies. Kept; consider retaking. - -### Batch w10 (`permit-mcp-gateway/audit-logs.mdx` and related pages) - -Sources checked: permitio/agent-security repo (consent-service, platform, gateway, packages/policy-management; default branch tarball), and docs/how-to/use-audit-logs/types-and-filtering.mdx. - -#### audit-logs.mdx -- `docs/permit-mcp-gateway/audit-logs.mdx`: "Decision: `Allow` or `Deny`" (reason: contradicts platform/src/components/audit-logs/audit-logs-table.tsx, which renders "Allowed"/"Denied"; changed) -- `docs/permit-mcp-gateway/audit-logs.mdx`: denial reasons "User not found" and "Resource not found" (reason: could not verify these strings; platform/src/lib/permit/audit-logs.ts only rewrites the no-role case to "No permission for 'X'" and passes other Permit reasons through; replaced with Permit denial codes user_not_synced and no_such_resource, linked) -- `docs/permit-mcp-gateway/audit-logs.mdx`: "The Permit Audit Log supports filtering by User, Resource, Action, Decision" (reason: contradicts how-to/use-audit-logs/types-and-filtering.mdx: the screen filters by user, date, decision, tenant; resource and action filters are API-only; changed) -- `docs/permit-mcp-gateway/audit-logs.mdx`: "Export or review the entries" for compliance reports (reason: could not verify an export feature on the Audit Log screen; replaced with the List audit logs API) -- `docs/permit-mcp-gateway/audit-logs.mdx`: gateway dashboard step "Filter by decision" on the MCP server audit log (reason: no decision filter in platform/src/components/audit-logs; moved the filter to the Permit dashboard) -- `docs/permit-mcp-gateway/audit-logs.mdx`: "The Permit dashboard shows the full policy evaluation chain, including which derived roles were checked" (reason: could not verify the derived-role detail; narrowed to the decision log's check and reason per types-and-filtering.mdx) -- `docs/permit-mcp-gateway/audit-logs.mdx`: added "Partial audit view" note above 50 agent registrations (verified: platform/src/schemas/audit-logs.ts MAX_FILTER_ITEMS = 50; components/audit-logs/partial-audit-alert.tsx) - -#### authentication-methods.mdx -- `docs/permit-mcp-gateway/authentication-methods.mdx`: OIDC callback URL "https://{subdomain}.agent.security/api/auth/callback/sso-{subdomain}" (reason: contradicts platform/src/components/hosts/auth-methods/oidc-provider-details.tsx, which shows `/api/auth/oauth2/callback/sso-{subdomain}` per the better-auth genericOAuth convention; prose and tables changed, fenced block logged in codefix_w10.md) -- `docs/permit-mcp-gateway/authentication-methods.mdx`: "Passkeys require an initial registration via another method (email/password or social login)" (reason: could not verify; consent-service has a passkey sign-in button but no passkey registration UI was found; reworded to "a user without a registered passkey can't sign in with a passkey, so keep another method on") -- `docs/permit-mcp-gateway/authentication-methods.mdx`: "SP Metadata XML: Download from the host settings page" (reason: platform saml-provider-details.tsx shows an "SP Metadata URL" read-only field, no download; changed) -- `docs/permit-mcp-gateway/authentication-methods.mdx`: "Azure AD Identifier" and "In Set up Permit MCP Gateway" (third-party UI labels, not verified against the current Azure portal; reworded to the Microsoft Entra identifier, noting older portals say Azure AD Identifier) -- `docs/permit-mcp-gateway/authentication-methods.mdx`: "seamless SSO experience" (reason: filler; removed) -- `docs/permit-mcp-gateway/authentication-methods.mdx`: kept and verified: 6-digit OTP with 5-minute expiry, IdP-initiated SAML disabled, InResponseTo validation, PEM check and all validation rules, Microsoft tenant default `common`, OIDC scopes, sign-in screen order, Create Account condition, force-redirect fallback message, domain intersection logic, default Email / Password only (consent-service/src/lib/auth.ts, lib/domain-filter.ts, lib/db/auth-config-types.ts, components/login/login-client.tsx, app/api/admin/auth-config/[subdomain]/route.ts) -- `docs/permit-mcp-gateway/authentication-methods.mdx`: Okta, Entra ID, and Google Workspace console click paths kept unverified (third-party UIs); added a note that console labels change - -#### consent-service.mdx -- `docs/permit-mcp-gateway/consent-service.mdx`: "Soft TTL (inactivity) 30 days: if no tool calls are made for 30 days, the session is removed" and "Hard TTL (absolute) 90 days: maximum session lifetime regardless of activity" (reason: contradicts gateway source. gateway/src/config.rs marks soft_ttl `#[allow(dead_code)] // Used by cleanup job (not yet implemented)`; McpSession::is_stale is dead code; gateway/src/storage/mcp/operations.rs touch_session, called on each MCP request from routes/public/mcp/mod.rs, re-sets the Redis EXPIRE to the 90-day hard TTL, so the 90 days restart on every use. Rewritten as "Redis removes the application session 90 days after the last tool call". CROSS-PAGE CONFLICT: guide.mdx (~line 218), advanced-features.mdx (~line 73), and overview.mdx still say 30 days without tool calls or 90 days after creation. Owner to confirm product behavior. The consent-service OAuth provider sets refreshTokenExpiresIn to 30 days, which may be an effective 30-day limit for MCP clients; not verified.) -- `docs/permit-mcp-gateway/consent-service.mdx`: "Manual revocation ... immediately invalidates the session" (reason: could not verify session deletion on revocation; aligned with platform.mdx and managing-humans-and-agents.mdx: the agent's next tool call to that server is denied) -- `docs/permit-mcp-gateway/consent-service.mdx`: "The user clicks **Authorize Agent**" (reason: contradicts consent-service/src/components/consent/steps/review-consent-step.tsx, whose buttons are "Accept" and "Deny"; changed) -- `docs/permit-mcp-gateway/consent-service.mdx`: added "For a server added through Dynamic MCPs, the user can also change the trust level of individual tools, up to the max trust level" (verified: review-consent-step.tsx allows per-tool edits only when mcp.isDynamic; mcp-consent-form.tsx sends per-tool trust only for dynamic servers). KNOWN CONFLICT for owner, not resolved: demos/n8n-linear-mcp-gateway.mdx shows per-tool trust at consent, while consent-service.mdx describes one slider capped by the admin maximum. Source shows one trust level for admin-imported servers and per-tool overrides only for dynamic MCP servers. Owner to confirm which case the n8n demo and its tool-import.png screenshot show. -- `docs/permit-mcp-gateway/consent-service.mdx`: "The upstream tokens are stored securely" (reason: unqualified security claim; reworded to "the gateway stores the upstream tokens in the user's session") -- `docs/permit-mcp-gateway/consent-service.mdx`: "handled transparently", "Reducing friction" (reason: filler; removed) -- `docs/permit-mcp-gateway/consent-service.mdx`: kept and verified: session keyed by client ID and subject in Redis (gateway PUT /mcp/sessions/{client_id}/{subject}), Permit sync before session creation, 403 above max trust, 5-minute upstream token refresh buffer (TOKEN_REFRESH_BUFFER_SECS=300), path-based `/mcp/{static_mcp_key}` route, `/.well-known/oauth-authorization-server` served by the gateway - -#### permit-integration.mdx -- `docs/permit-mcp-gateway/permit-integration.mdx`: "Role assignments linking each action to the appropriate trust level" (reason: wrong term; role permissions grant actions to roles. Verified: packages/policy-management/src/resources/resources.ts builds `low`/`medium`/`high` roles with `permissions` and `extends`; changed to permissions) -- `docs/permit-mcp-gateway/permit-integration.mdx`: "Trust level | Permit role `{server}-low` | Permissions" (reason: conflated two role sets; source has `low`/`medium`/`high` roles on the MCP server resource that hold permissions, and `{server}-low`/`-medium`/`-high` roles on user_profile assigned to agents; table split) -- `docs/permit-mcp-gateway/permit-integration.mdx`: "you get the full power of Permit's policy engine", "Permit is not a peripheral integration", "deep integration" (reason: hype; removed) -- `docs/permit-mcp-gateway/permit-integration.mdx`: "RBAC, ABAC, and ReBAC policy models", "Real-time policy updates via OPAL", "Policy-as-code via Terraform provider", "Local PDP option ... decisions stay within your network" (reason: could not verify for the gateway; gateway/src/config.rs defaults PERMIT_PDP_URL to https://cloud-pdp.api.permit.io, and the Cloud PDP doesn't support ABAC per types-and-filtering.mdx. Replaced with the Cloud PDP default, a link to enterprise-deployment's Local PDP section, next-call policy changes, the audit log, and the Permit API) -- `docs/permit-mcp-gateway/permit-integration.mdx`: "The environment name typically matches the host name" (reason: could not verify; replaced with reading the linked project and environment on the host. Verified that an environment can attach to only one host: platform/src/app/api/hosts/route.ts) -- `docs/permit-mcp-gateway/permit-integration.mdx`: allow-list route table (`POST /api/mcp/connect`, `/api/mcp/oauth/start`, `/api/mcp/preprovisioned-clients`) (reason: internal routes, volatile; the routes exist, table replaced with the behavior. `POST /api/consent/accept` and its 403 message kept in the three-layer section, verified in consent-service/src/app/api/consent/accept/route.ts) -- `docs/permit-mcp-gateway/permit-integration.mdx`: "Allowing the same MCP server resource to be shared across tenants if needed" (reason: could not verify; removed. `default` tenant verified for static and dynamic resources) -- `docs/permit-mcp-gateway/permit-integration.mdx`: effective permission rows where the profile relation is above the agent role, for example `{server}-medium` + `high` relation = medium (kept, unverified: the 9 derived-role rules in packages/policy-management/src/derived-roles/derived-roles.ts have no rule for `{server}-medium` + `high`, `{server}-low` + `medium`, or `{server}-low` + `high`, and platform/src/app/api/humans/[key]/mcp-access/route.ts creates a single relation tuple per grant. Owner to confirm how those combinations derive a role; possible product bug or missing detail) -- `docs/permit-mcp-gateway/permit-integration.mdx`: "Key Takeaways" section (reason: summary section with repeated claims such as "Changes are instant"; removed) - -### Batch u11 (`how-to/build-policies` and related pages) - -- `docs/how-to/build-policies/policy-basics.mdx`: "Roles exist on an organization level - whether you change project, tenant, or environment, the same roles exist for you." (reason: contradicts API spec path /v2/schema/{proj_id}/{env_id}/roles and building-rbac-policy.mdx "created at the environment level"; rewritten as per-environment) -- `docs/how-to/build-policies/policy-basics.mdx`: "Roles are assigned to users via the User Management page" linking to /manage-your-account/workspace-settings#member-management (reason: that page is dashboard members, not users; replaced with Directory screen and a users-vs-members note) -- `docs/how-to/build-policies/policy-basics.mdx`: "Permissions ... can also be assigned directly to individual users or entities" (reason: could not verify direct user permissions in Permit's RBAC model) -- `docs/how-to/build-policies/policy-basics.mdx`: "The default settings will only be applied to new resources created from the dashboard." (reason: could not verify whether API-created resources also get default permissions) -- `docs/how-to/build-policies/policy-basics.mdx`: "Users are contained within tenants, and can only access the resources within their tenant." (reason: overgeneralized; user sets are not tenant-bound per building-abac-policy.mdx; replaced with role assignments scoped per tenant) -- `docs/how-to/build-policies/policy-basics.mdx`: marketing intro ("power of a powerful authorization engines", "champions the best practices", "ensuring scalability, traceability", "extremely simple, yet vastly powerful") (reason: unverifiable marketing) -- `docs/how-to/build-policies/policy-basics.mdx`: stray Hebrew character (U+05BF) before the screenshots; link to http://localhost:3000/integrations/gitops/github replaced with /integrations/gitops/github. -- `docs/how-to/build-policies/rbac/components.mdx`: "Top level represents the fact that Roles have higher priority in policy evaluation than Instance-level Roles." (reason: could not verify; no evidence in docs or API of role priority; top-level now defined as tenant-wide per mesa-verde.mdx) -- `docs/how-to/build-policies/rbac/components.mdx`: "Below is an example of a two roles; an Admin and a Friend ... card resource" (reason: contradicts screenshot rbac-0.png, which shows Admin and Customer roles on a document resource; text fixed to match). Duplicate arcade demo removed; page links to the RBAC overview demo. -- `docs/how-to/build-policies/rbac/overview.mdx`: "It's the most basic and simple approach to access management." (reason: generalization) -- `docs/how-to/build-policies/rbac/building-rbac-policy.mdx`: truncated "Role Attributes" section ("To achieve more granularity in role creation, we") (reason: incomplete; replaced with a link to defining-attributes#define-role-attributes) -- `docs/how-to/build-policies/rebac/overview.mdx`: "Given their ability to manage high volumes of data while maintaining consistency, these systems prove effective in large-scale environments." (reason: vague unverified scale claim) -- `docs/how-to/build-policies/rebac/overview.mdx`: "We want to grant them editing access to all files the employee data files" (reason: contradicts the policy that uses Legal_Docs; text now says legal documents) -- `docs/how-to/build-policies/rebac/building-rebac-policies.mdx`: "Once you successfully define the relationships on the roles - it will automatically create the roles for you in the policy editor." (reason: could not verify what is auto-created) -- `docs/how-to/build-policies/rebac/building-rebac-policies.mdx`: "Permit implementation of Relationship-Based Access Control (RBAC) is fully compatible with the Tuples convention" (reason: acronym wrong, and "fully compatible" unverified; softened to "follows the tuple convention") -- `docs/how-to/build-policies/abac/defining-attributes.mdx`: "resource attributes can only be pushed in permit.check and as a custom Rego function" (reason: contradicts API spec ResourceInstanceCreate.attributes and overview/sync-applications-data.mdx, which store resource instance attributes via API or Directory > Instances) -- `docs/how-to/build-policies/abac/defining-attributes.mdx`: "Permit supports attributes on three different objects" followed by four (reason: count wrong; fixed to four) -- `docs/how-to/build-policies/abac/defining-attributes.mdx`: tenant attributes UI path "Manage tenants ... open the Tenant Attributes panel" (reason: could not verify a Tenant Attributes panel inside Manage Tenants; kept Settings > Manage Tenants only) -- `docs/how-to/build-policies/abac/patterns.mdx`: "Once we add ReBAC and groups natively to Permit.io - those would be the default recommended way to implement groups." (reason: stale; ReBAC and Groups API exist) -- `docs/how-to/build-policies/abac/patterns.mdx`: "ReBAC is a subset of ABAC" (reason: unverified generalization) -- `docs/how-to/build-policies/abac/patterns.mdx` (media): /img/resource_ownership.png shows attribute `resource.owner` while the code sample uses `owners` (reason: screenshot and code disagree; prose notes the key must match; consider retaking the screenshot) -- `docs/how-to/build-policies/abac/building-abac-policy.mdx` (media): /img/abac-updated/user-set-0.png shows conditions on `tenant.university` and `tenant.is_full_time`, while the steps create user attributes (reason: screenshot contradicts steps; kept, consider retaking). Set names also differ across screenshots ("Full-time Stanford Student(s)", "Bicycle(s) available after 5pm"). -- `docs/how-to/build-policies/abac/building-abac-policy.mdx`: resource set condition "`resource.time` > \"17:00\"" (reason: contradicts screenshot, which uses Number type and greater-than 17; text fixed) -- `docs/how-to/build-policies/abac/building-abac-policy.mdx`: tenant attributes "Navigate to the Users panel, click the Tenant Attributes button, click Add New Tenant Attribute" (reason: contradicts screenshot, which shows Directory Settings > Tenant Attributes > Add Attribute) -- `docs/how-to/build-policies/abac/building-abac-policy.mdx`: warning "Tenant boundaries are not automatically enforced for user sets" kept and expanded with its consequence; owner should confirm. -- `docs/how-to/ownership.mdx`: "As `file` is set as parent of `folder`, all permissions set on a `folder` will automatically propagate to `files`" (reason: reversed; screenshots show folder is parent of file; also propagation requires a role derivation, now an explicit step linking to building-rebac-policies#defining-role-derivations) -- `docs/how-to/ownership.mdx`: "The ABAC condition will compare the file_ownership attribute" (reason: screenshots show attribute `owner`; file_ownership is the resource set key) -- `docs/how-to/ownership.mdx`: "Go to the Policy section and click on Resource instances" (reason: screenshot 7 shows an older UI; current docs place instances in Directory > Instances; step rewritten to Directory) -- `docs/how-to/ownership.mdx`: "Go to the ABAC Rules tab, and enable ABAC Options." (reason: could not verify an enable toggle) - -### Batch w11 (`permit-mcp-gateway/http-egress-proxy` and related pages) - -- `docs/permit-mcp-gateway/http-egress-proxy/index.mdx`: "The HTTP Egress Proxy is a newer capability and is enabled per environment" (reason: stale dated wording; replaced with "must be enabled for your account") -- `docs/permit-mcp-gateway/http-egress-proxy/index.mdx`: "High-risk requests can be routed to a human for approval before they're forwarded (optional, per host)" (reason: contradicts agent-security docs/reference/http-proxy-and-cli.md step 9: the intent guardian StepUp/Defer verdict is the only HITL trigger on the proxy path, and the guardian requires agent identity. Rewritten to match egress-rules.mdx) -- `docs/permit-mcp-gateway/http-egress-proxy/index.mdx`: "Every decision ... is logged" (reason: security.mdx and the gateway security model say audit is best-effort, fire-and-forget; softened to best-effort) -- `docs/permit-mcp-gateway/http-egress-proxy/cli.mdx`, `egress-rules.mdx`, `quickstart.mdx`: "there is no CLI command for authoring them yet" (reason: roadmap wording; restated as present fact, verified in packages/agent-security-cli/README.md: no `asg proxy workflow` command) -- `docs/permit-mcp-gateway/http-egress-proxy/security.mdx`: "a recent sign-in, within the last day, is required" (reason: could not verify in permitio/agent-security docs/reference/http-proxy-and-cli.md or security-model.md; removed) -- `docs/permit-mcp-gateway/http-egress-proxy/quickstart.mdx`, `connecting-agents.mdx`: `asg run` linked to cli.mdx which did not document it (resolved: documented `asg init` and `asg run` in cli.mdx from packages/agent-security-cli/src/commands/run.ts and init.ts; links now point to /permit-mcp-gateway/http-egress-proxy/cli#launch-an-agent-with-asg-run) -- Verified and kept: rate-limit defaults 600 per host / 1200 per eTLD+1 / 60 s window (gateway/src/config.rs, PROXY_RATE_LIMIT_PER_HOST, PROXY_RATE_LIMIT_PER_ETLD, PROXY_RATE_LIMIT_WINDOW_SECS), now labeled as gateway defaults with the setting names; "exactly twelve distinct words" (CLI README and ref doc); VAULT_ENABLED / AWS_KMS_KEY_ID (gateway/src/token_vault/config.rs); AWS STS session TTL 15 min to 12 h and form label "External ID reference" (platform/src/components/proxy/credential-sheet.tsx). -- Unverified but kept (owner to confirm): dashboard navigation labels "CLIs / APIs → Workflows/Credentials/Overview/Activity" (CLI README calls the section "Proxy -> Workflows" in the Platform UI); method class membership `read` = GET/HEAD/OPTIONS, `write` = POST/PUT/PATCH; revocation "from their account". -- Source conflict to flag upstream: permitio/agent-security docs/guides/asg-cli-quickstart.md says `asg run` reuses a cached token; run.ts and the CLI README say there is no token cache and every launch asks for consent. Docs follow run.ts. - -### Batch w12 (`embeddable-uis/element-login.mdx` and related pages) - -#### Decisions and cross-page conflicts -- `docs/embeddable-uis/element-login.mdx` and `embedding-elements.mdx`: Login Errors tables had drifted (element-login lacked `FORBIDDEN_ACCESS`). element-login (title "Log users in to Permit Elements") now owns the four-row table; the four codes match `ElementsApiErrors` in permit-node and `LoginAsErrorMessages` in permit-python. embedding-elements keeps a short `#login-errors` section that links to it, and troubleshooting links to `/embeddable-uis/element-login#login-errors` (was a link with no anchor). embedding-elements keeps its frontendOnly and logout code blocks (code guard) but links to element-login for parameters and other methods. -- Button name: "Get Code" (embedding-elements) vs "Generate Code" (element pages). Screenshot `static/img/elements/troubleshooting/generate-code.png` and `emails/email-notification-toggle.png` show **Generate Code**; the dialog it opens is titled "Element Embed Code" with a **Copy Code** button (`user-management/EmbedCode.png`). All pages use "Generate Code". -- `docs/embeddable-uis/webhooks.mdx`: "Current flow" vs "With the new approve invite flow applied" does not say which flow is live, or what setting selects it. Reworded neutrally as two flows ("Invite creates the user" / "Invite requires approval"); anchors `#current-flow` and `#with-the-new-approve-invite-flow-applied` kept. Added "The webhook type you receive tells you which flow applied: `create_user` or `invite_user`" (inferred from the payload schemas, not verified). Owner to confirm which flow is default and how it is chosen. -- `docs/embeddable-uis/element/operation-approval.mdx`: "Once the request is approved or denied, the user will receive approval for the requested action" (reason: contradicts itself). Replaced with: approval assigns the `_Approved_` role on the resource instance (from approval-management.mdx), denial doesn't, and a webhook is sent (from the page and its diagram). -- `docs/embeddable-uis/element/access-request.mdx`: reviewer described as "the workspace owner" and as "Level 1 role in User Management". Unified as "a user whose role is at Level 1 (Workspace Owner)", matching the permission-levels screenshot labels. -- `docs/embeddable-uis/element/operation-approval.mdx`: role assignment example `transfer:transfer-1#_Reviewer_` vs screenshot `addPermissionForReviewer.png`, which shows the role key `_reviewer_` (lowercase) on resource `transfar`. Kept `_Reviewer_` in text; owner to confirm the role key case. -- `docs/embeddable-uis/element/approval-management.mdx`: note "it is crucial to select the tenant" while the iframe sample has no `tenantKey`. Replaced with: the example has no `tenantKey`; if the generated snippet includes it, set it. Owner to confirm whether Approval Management iframes take `tenantKey`. -- `docs/embeddable-uis/overview.mdx`: ElementTile redirects `/features/permit-elements/element/audit-logs` and `/features/permit-elements/element/approval-flows` changed to `/embeddable-uis/element/audit-logs` and `/embeddable-uis/element/access-request` (redirects.js targets). ActionContainer anchors `user-management#customising-your-element` and `#configure-your-webhook` (did not exist) now point to `/embeddable-uis/embedding-elements#customize-the-element` (new heading id on the customization section) and `/embeddable-uis/webhooks#configure-your-webhook`. "Get started" now points to embedding-elements. Slack link `io.permit.io/docs-to-slack` changed to `io.permit.io/slack`. -- access-request, approval-management, operation-approval, audit-logs: "Embedding Elements" links changed from `/embeddable-uis/overview` to `/embeddable-uis/embedding-elements`. The shared YouTube embed is kept on all five element pages without repeated intro text; its iframe title changed from "YouTube video player" to "Permit Elements video" (video content not reviewed). - -#### Removed or reworded claims -- `docs/embeddable-uis/overview.mdx`: "We add new elements over time" (reason: roadmap wording). Replaced with a request-an-element pointer to Slack. -- `docs/embeddable-uis/element/audit-logs.mdx`: "This element gives full control over your applications, enforcing security" (reason: hype, unverifiable). Replaced with the columns visible in `audit-logs-full.png` (Time, User, Resource, Action). The page's embed steps (create in Elements screen, permission levels, Generate Code, login) are generalized from the other element pages, not verified for this element type specifically. -- `docs/embeddable-uis/overview.mdx`: tile description "Monitor decisions made against each policy" kept in the tile component, but the new table describes what the screenshot shows (user actions on resources). -- `docs/embeddable-uis/permission-levels.mdx`: "As more elements come out ... Some elements will be view only, which means you can only expect the Hidden Roles and the Viewer levels" (reason: dated wording, could not verify which types are view-only). Replaced with "Some element types don't use all five levels. The configuration form of each element shows the levels that element type supports." Level descriptions now use the dashboard labels in `permission-levels-full.png` ("Can assign roles, and Add / Remove users"; Manager "Can assign level 2-4 roles"), replacing "cannot make changes to the overall workspace" (unverified). Level 4 = Assignable Roles matches API enum `ElementsPermissionLevel` (LEVEL_1..LEVEL_4, HIDDEN). -- `docs/embeddable-uis/permission-levels.mdx`: added "If a user opens the element with a role in Hidden Roles, the login fails with `INVALID_PERMISSION_LEVEL`" (from the original embedding-elements error table, which said "usually"; not verified in source). -- `docs/embeddable-uis/troubleshooting.mdx`: Set-Cookie blocked fix "turn on the third-party cookies in the browser settings or set the SameSite attribute to None in the server response" (reason: end users can't be asked to change browser settings, and the `permit_session` cookie is set by Permit, not by the customer's server). Replaced with: use the `supportsPrivateBrowser` login method for users; allow third-party cookies only in your own browser to confirm the cause. -- `docs/embeddable-uis/troubleshooting.mdx`: "the user will be redirected to the /login_elements page" reworded to "A successful login makes a request to /login_elements" (the user isn't redirected; permit-js uses a hidden iframe or AJAX). Kept unverified that every method produces a `/login_elements` request (diagram shows it for backend methods only). -- `docs/embeddable-uis/webhooks.mdx`: "If your endpoint fails to do this, the webhook may consider the delivery a failure and retry, causing unnecessary traffic" (reason: retry behavior could not be verified). Removed. -- `docs/embeddable-uis/webhooks.mdx`: "we provide a input box so you can enter your secret, and use it to validate incoming data" replaced with "Permit uses the secret as a bearer token to authenticate its requests"; check the `Authorization` header. Based on API spec `WebhookCreateWithElements.bearer_token` ("An optional bearer token to use to authenticate the request"); the `Authorization: Bearer` header format itself is inferred, not verified in the sender source. -- `docs/embeddable-uis/webhooks.mdx`: "This extra approval step introduces a security advantage, since it ensures that only verified and authorized users can complete the process" reworded to "Your application can verify the invited person first, so only users you approve get an account." -- `docs/embeddable-uis/webhooks.mdx`: Access Request `status` values listed as `pending`, `approved`, `denied`, `canceled` from the API spec `RequestStatus` enum. -- `docs/embeddable-uis/email-configuration-and-templates.mdx`: "Permit Elements currently supports the following email provider" (reason: dated wording). Now "Permit Elements sends email through an SMTP provider." "Inviting Approving the invited user using an SDK" (garbled) removed. "The invite code is the `user_invite_id`" is verified by permit-js `approve()`, which posts to `/user_invites/{inviteCode}/approve`. SMTP settings location changed to the **Settings** button on the Permit Elements screen, per `emails/elements-settings.png`. -- `docs/embeddable-uis/email-configuration-and-templates.mdx`: `{{ redirect_to }}` "will be replaced with the URL that you filled in the Redirect To field" reworded to "the invite link, built from the Redirect To URL" (the email link carries `invite_code`); unverified detail. -- `docs/embeddable-uis/element-login.mdx`: "Permit Element is now compatible with private browsers, such as Chrome Incognito Mode and Safari" (reason: dated wording). Replaced with the mechanism from permit-js `sendToken.ts` (token posted to the iframe with `postMessage`). -- `docs/embeddable-uis/element-login.mdx`: "Ensuring Login Before Loading the Iframe ... preventing issues with private browsing mode. Add with an authenticated session to Permit cloud." (reason: dangling sentence; for `supportsPrivateBrowser`, permit-js retries until the iframe exists, so the order isn't what matters). Replaced with "Match the iframe URL exactly": permit-js finds the iframe by `src === elementIframeUrl`. Anchor `#ensuring-login-before-loading-the-iframe` kept on that section. The general rule "call login before the iframe renders" moved to the login step. -- `docs/embeddable-uis/element-login.mdx` (kept, unverified): `ticket.element_bearer_token` is not in the typed `loginAs` responses of permit-node or permit-python (they spread extra API fields, so it may be present at runtime). The requirement to return it in a `url` field is verified (permit-js reads `data.url`). The version floor "permit-js 0.5.2" is kept; 0.5.2 exists on npm but the release that added `supportsPrivateBrowser` was not checked. -- `docs/embeddable-uis/element-login.mdx`: added verified details from permit-js: `LoginMethod.cookie` is the default; cookie login loads `loginUrl` in a hidden iframe with a `tenant` query parameter; bearer/header login POSTs and reads `url` from the JSON response (so `ticket.content` = `{ url: redirect_url }`, verified in permit-node); `frontendOnly` requires `userJwt`, `tenant`, `envId`, ignores `loginUrl`, and accepts `userKeyClaim`; `supportsPrivateBrowser` requires `elementIframeUrl`. -- `docs/embeddable-uis/user-preview.mdx`: alt text "Audit Logs Element" on the preview screenshot (reason: wrong image description). Steps now use labels visible in `generic/element-preview.png` (End User Preview, level dropdown with "(Empty)", Tenant dropdown, desktop/mobile icons, "Nothing to Preview"). The tenant-dropdown visibility note is kept from the original, unverified. - -#### Anchors not preserved -- `docs/embeddable-uis/troubleshooting.mdx`: headings "🛠️ Error `401 Unauthorized` -" and "🛠️ Page Not Found (404) -" had slugs starting with an invisible U+FE0F character (`️-error-401-unauthorized--`, `️-page-not-found-404--`). No page links to them; they were not kept as explicit ids. -- Removed H1s (`# Permit Elements`, `# Permissions Levels`, `# Live Element Preview`, `# Email Configuration and Templates`, `# Access Request Element`, etc.); nothing in docs or src links to those slugs. - -### Batch u12 (`faq.mdx` and related pages) - -#### Removed or changed - -- `docs/faq.mdx`: "The free tier includes all features for up to 1,000 monthly active users, with no credit card required." (reason: partly verified. https://www.permit.io/pricing shows the Community plan "Free Forever", MAU 1000, and "All features are open to all tiers". "No credit card required" does not appear on the pricing page, so it was removed.) -- `docs/faq.mdx`: "Timestamps are stored with millisecond precision. Fetch logs through the API with `timestamp_from` and `timestamp_to`" (reason: contradicts the API spec. `GET /v2/activity` takes `timestamp_from` and `timestamp_until`, both integers in seconds since the epoch; there is no `timestamp_to`. Millisecond storage could not be verified. Rewritten to use `timestamp_until` and dedupe on the event `id`.) -- `docs/faq.mdx`: house/front-door metaphor for authentication vs authorization (reason: style rule against metaphors; replaced with a table.) -- `docs/faq.mdx`: "Within team management, I can add new people to the team, but not assign them any other role, apart from Admin." (reason: stale. The Members tab offers Workspace Owner, Editor, and Viewer roles plus project and environment roles. Heading reworded with the old anchor kept, and the answer points to Member management.) -- `docs/status.mdx`: frontmatter "Check the live status and uptime of Permit.io's Cloud PDP, API, and dashboard." (reason: the live status page (https://permit-io.instatus.com/) lists Permit.io Backend, OPAL, Frontend, Marketing Website, PDP Deltas, and PDP Data in US East and Europe. It has no "Cloud PDP" entry. The description and body now list what the page shows. Note: https://status.permit.io does not resolve in DNS, so the direct link uses permit-io.instatus.com.) -- `docs/getting-started/slack-support.mdx`: "/permit-escalate - Pro/Enterprise Support Only" and "Works in private channels and DMs, not in public channels" (reason: kept but only partly verified. The pricing page lists "Dedicated Slack Channel" for Pro and Enterprise only, which matches. The public-channel restriction could not be verified. Owner should confirm.) -- `docs/getting-started/slack-support.mdx`: image alt "Slack general channel" for /img/slack/slack-1.png (reason: wrong. The screenshot is the Slack invite page "See what Permit is up to"; alt text corrected. The screenshot shows real member names; consider replacing it.) -- `docs/manage-your-account/projects-and-env.mdx`: removed the duplicate "Creating a new Environment" video and text (reason: duplicate of creating-environments, which now owns the task; heading kept with anchor `creating-a-new-environment` and a link to the owner page.) -- `docs/manage-your-account/projects-and-env.mdx`: dangling e-learning example "John Smith ... enrolled as a student in ... Introduction to Web Development" (reason: example never completed; removed.) -- `docs/manage-your-account/projects-and-env.mdx`: "By default, we defined the Default Project for you." (reason: kept as "A new workspace includes a project named Default Project", based on permit-backend `services/common/consts.py` DEFAULT_PROJECT_NAME = "Default Project".) -- `docs/manage-your-account/permit-logs.mdx`: "This log will only show changes made via the Permit.io dashboard. If you wish to see changes made via the Permit.io REST API, you should check out the API log." (reason: contradicts the API spec. `GET /v2/activity` filters by `actor_type` of `member`, `user`, or `api_key`, so the activity log is not limited to dashboard changes. Removed.) -- `docs/manage-your-account/permit-logs.mdx`: "Only workspace owners may view activity logs / the API log." (reason: kept from the original; could not verify in source.) -- `docs/manage-your-account/workspace-settings.mdx`: "their access level will be `Mixed`, if its more than two projects with different access" (reason: the "more than two projects" threshold could not be verified; the screenshot shows `Mixed` for a member with 2 projects. Rewritten as "when those roles differ in access level".) -- `docs/manage-your-account/workspace-settings.mdx`: "Organization Keys ... are primarily accessible by top-level administrators", "Project Keys ... access is typically granted to project managers", "Environment Keys ... Developers and operations teams usually manage these" (reason: speculative, not verifiable. Replaced with a scope table based on docs/api/api-with-cli.mdx.) -- `docs/manage-your-account/workspace-settings.mdx`: "Enterprise and Pro (for an additional fee) customers can request a tailored DPA" (reason: verified and kept. The pricing page row "GDPR, CCPA, DPA Agreement" shows Pro "$500/y" and Enterprise "Included".) -- `docs/manage-your-account/workspace-settings.mdx`: "if you must work with PII you can keep it solely on your self-hosted PDPs" (reason: could not verify a supported mechanism for keeping PII only on self-hosted PDPs. Removed. Kept that the user key is the only required user field, per the UserCreate schema in the API spec.) -- `docs/manage-your-account/workspace-settings.mdx`: real employee name "Shaul, one of our talented engineers" (reason: personal data and hype; example now describes "a member". The screenshot mixed-access-level.png still shows real @permit.io emails; consider replacing it.) -- `docs/manage-your-account/workspace-usage.mdx`: "Permit.io calculates your billing based on the number of Monthly Active Users (MAUs) and Tenants" (reason: pricing page shows MAU and tenant quotas per plan among other limits; reworded to "Permit plans set quotas on MAUs and tenants, among other limits" and linked to pricing.) -- `docs/manage-your-account/workspace-api.mdx`: "Environments: Projects API - requires a Project level API key" (reason: link was labeled "Projects API" but pointed to Environments; relabeled. Org-level keys also work per api-with-cli.mdx, so the text says project-level or organization-level.) - -#### Added and verified - -- `docs/how-to/bulk-operations.mdx`: per-call limits (users 3,000, tenants 2,000, resource instances 3,000, role assignments 2,000, roles 2,000, relationship tuples 1,000) verified in permitio/permit-deployments `chart-values/backend/values-prod-us-east-2-v2.yaml` and `values-prod-eu-central-1.yaml` (BULK_LIMIT_*). Over-limit HTTP 403 and empty-request HTTP 400 verified in permitio/permit-backend `api/common/bulk_utils.py` `check_bulk_size`. The limits are deployment config and can change. -- `docs/manage-your-account/creating-environments.mdx`: default roles apply only to resources created by a workspace member, not by API keys (permit-backend `api/routers/schema_routes/resources.py`, `assign_default_roles=... viewer.type == ViewerContextType.member and env.settings.get("enable_default_roles") is True`). Copy permissions, same-project restriction, `conflict_strategy` values `fail`/`overwrite`, and `scope` keys verified in the API spec. -- `docs/manage-your-account/projects-and-env.mdx` and `workspace-settings.mdx`: "rotating an API key revokes the old key" verified in permit-backend `services/api_keys.py` `rotate_secret` ("the previous value must stop authenticating"). -- `docs/manage-your-account/workspace-api.mdx`: "Create Organization requires a special permission" verified in the API spec description of `POST /v2/orgs`. - -#### Slack invite URL (not changed) - -- `https://io.permit.io/slack` (title "SM to community") and `https://io.permit.io/docs-to-slack` (title "docs-to-slack") both return HTTP 200 and meta-refresh to the same Slack invite. docs-to-slack looks like the tracked link for docs, so existing docs-to-slack links in faq.mdx and slack-support.mdx were kept, and new links in status.mdx and bulk-operations.mdx use docs-to-slack. workspace-api.mdx keeps its original io.permit.io/slack link. STYLE_GUIDE.md says io.permit.io/slack; the coordinator should pick one URL and apply it site-wide. - -### Batch w13 (`api/api-with-cli.mdx` and related pages) - -- `docs/api/api-with-cli.mdx`: rate-limit table "Schema write requests (`POST /v2/schema/*`) 40 req/min", "Member requests (`/v2/members/*`) 50 req/min", "DELETE requests 60 req/min", "Bulk requests 100 req / 10 min", "All write requests (POST, PUT, DELETE) 300 req/min", "All requests 1,000 req/min" (reason: could not verify; not in the OpenAPI spec, pricing page, or other docs. Removed the numbers, kept the `#rate-limiting` section with HTTP 429 behavior because /how-to/bulk-operations links to it. Owner: confirm the numbers to restore the table.) -- `docs/api/api-with-cli.mdx`: "EU region (available at Permit Pro)" (reason: pricing page shows "Deployment Regions: Single" for Community/Startup, "Single (selectable)" for Pro, "Multiple (optional)" for Enterprise, with default regions US East 2 and EU Central 1. Replaced with "Which regions you can choose depends on your plan" plus a pricing link. `api.eu.permit.io` verified reachable (HTTP 200 on /v2/openapi.json).) -- `docs/api/api-with-cli.mdx`: "get all the users in your organization" (reason: contradicts the endpoint, which is per environment: /v2/facts/{proj}/{env}/users. Reworded.) -- `docs/api/background-tasks.mdx`: "Background tasks may take a long time, up to 30 minutes" (reason: could not verify; not in the spec. Removed.) -- `docs/api/background-tasks.mdx`: prose "the status will be `failed,`" (reason: contradicts OpenAPI TaskStatus enum: processing, success, failure, cancelled. Prose now says `failure`; JSON sample logged in codefix_w13.md.) -- `docs/api/pdp-webhooks.mdx`: "If it doesn't work after several retries, Permit's support team will be notified automatically so they can look into the issue." (reason: could not verify. Removed.) -- `docs/api/pdp-webhooks.mdx`: "make sure your PDP is of at least version 0.2.24. This feature won't work with older PDPs." (reason: could not verify the minimum version in permitio/PDP (GitHub code search was rate-limited). Removed. Owner: restore if confirmed.) -- `docs/api/pdp-webhooks.mdx`: link "https://api.permit.io/v2/redoc#tag/Webhooks" (reason: the public OpenAPI spec has no webhooks path or Webhooks tag, so the anchor does not resolve. The endpoint itself exists: unauthenticated POST/GET to /v2/projects/x/envs/y/webhooks returns 401, /webooks returns 404. Link removed. Owner: consider publishing the webhooks endpoint in the spec.) -- `docs/api/pdp-statistics.mdx`: link /overview/connecting-your-app#1-get-your-permit-environment-api-key (reason: stale per brief; replaced with /overview/get-api-key.) -- `docs/api/pdp-api-reference.mdx`: frontmatter promised "hosted evaluation PDP" coverage the page lacked (reason: added Cloud PDP base URL https://cloudpdp.api.permit.io; /openapi.json, /redoc, /scalar all return 200. /scalar route verified in permitio/PDP horizon/pdp.py.) -- `docs/api/v2-migration-guide.mdx`: "In the near future, we'll make it possible to directly duplicate and merge environments just like git branches." (reason: roadmap/stale. Removed; linked /manage-your-account/creating-environments, which documents copy and merge.) -- `docs/api/v2-migration-guide.mdx`: "which was the current version until recently" (reason: dated wording. Removed.) -- `docs/api/v2-migration-guide.mdx`: "The v2 API was built from the ground up to be more convenient to use and faster than the v1 API", "should work identically but be a lot faster, as we've also done major optimization work on the v2 PDPs" (reason: unverified performance claims. Removed.) -- `docs/api/v2-migration-guide.mdx`: "While you can keep using v1 for a while, we'll eventually retire it", "We're going to keep supporting the v1 API for the foreseeable future" (reason: roadmap. Removed; kept "deprecated".) -- `docs/api/v2-migration-guide.mdx`: "newly generated [API keys] are much shorter than before... Existing API keys work normally, and new v2 keys work on v1 as expected" (reason: could not verify. Removed; kept "authenticate the same way".) -- `docs/api/v2-migration-guide.mdx`: "almost no one is using them anyway" (reason: unverifiable generalization. Removed.) -- `docs/api/v2-migration-guide.mdx`: compatibility environment named three ways: "v1compat_global_env" in project "v1compat_global_project", "v1_global_env", and "v2_global_env" in project "v1_global_project" (reason: contradictory. Page now uses the names in the code sample, `v2_global_env` in `v1_global_project`. Owner: confirm the real names; if they are v1compat_*, the code sample needs a fix too.) -- `docs/api/v2-migration-guide.mdx`: image "permitio/sidecar-v2" vs code sample "permitio/pdp-v2" (reason: contradictory. Page uses `permitio/pdp-v2`, which matches /overview/run-pdp.) -- `docs/api/v2-migration-guide.mdx`: Microsoft / Windows / Azure / Flight Simulator as the example organization and projects (reason: real company; style guide requires fictional examples. Replaced with Acme Corp, `billing`, `crm` in prose tables.) -- `docs/api/v2-migration-guide.mdx`: v2 sample `permit.api.sync_user(user)` (note: still works but is marked deprecated in permit-python permit/api/deprecated.py, "use permit.api.users.sync() instead". Prose now says so; code unchanged.) -- `docs/api/rebac/groups/groups.mdx`: "Previous GET endpoints are considered deprecated... They should not be used and will be removed in the future", "new and improved versions that offer better performance" (reason: spec marks only GET /groups and GET /groups/{group_instance_key} as deprecated; performance and removal claims unverified. Replaced with the spec facts: use /groups/direct.) -- `docs/api/rebac/groups/groups.mdx`: "The name of this relation will be `team_group`" and "The name of this relation will be `group`" (reason: relation names not in the spec; spec only says a relation, relationship, and derivation are created. Removed names.) -- `docs/api/rebac/groups/groups.mdx` and `groups-ui.mdx`: "Extended support for this function may be added in the future to allow assignment between groups with different resource types." (reason: roadmap. Removed; kept the same-resource-type limitation, once, in groups.mdx.) -- `docs/api/rebac/groups/groups.mdx`: list, children, parents, users, roles GET endpoints described as recommended with "enhanced performance" (reason: spec labels children/parents/users/roles list endpoints "(EAP)". Table now marks them "Early access".) -- `docs/api/rebac/groups/groups-ui.mdx`: "Key Benefits of Using Groups UI" and generic "Best Practices" list (reason: marketing/filler, not task content. Removed.) Also removed the quoted UI helper strings ("The description reads: ...") as volatile. -- `docs/api/rebac/groups/groups-ui.mdx`: "Child groups inherit relationship configurations from parent groups" (reason: direction of inheritance not verifiable from spec ("This group will inherit the group's roles"). Replaced with a link to the Groups API page.) -- `docs/api/rebac/rebac-api-calls.mdx`: role derivation Base URL pointed at implicit_grants while the example PATCHes /resources/file/roles/editor (reason: both are valid per spec: PATCH ResourceRoleUpdate has granted_to; POST implicit_grants takes DerivedRoleRuleCreate. Page now documents both.) - -### Batch w14 (`ai-security/access-request-mcp` and related pages) - -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "This setup enables ReBAC role checks and contextual permission logic not available in the default cloud PDP." (reason: contradicts /concepts/pdp/cloud-pdp-capabilities, which lists ReBAC as supported on the Cloud PDP; only ABAC and custom Rego need an Edge PDP. Rewritten to say ABAC needs an Edge PDP.) The permit-mcp example README repeats the stale claim ("ReBAC ... not yet available in the cloud PDP"); the repo README should be updated by its owner. -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "`OPERATION_ELEMENTS_CONFIG_ID` | ID of the operation approval element. Found under Elements > Approval Management." (reason: self-contradictory; permit-mcp README says the variable is the Approval Management element ID. Kept the README version.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "`PROJECT_ID` ... Found in the Permit dashboard under Project Settings" and "`ACCESS_ELEMENTS_CONFIG_ID` ... Found under Elements > User Management" (reason: could not verify the UI location; replaced with links to /api/examples/get-project-and-env and the element's Get Code dialog, which the screenshots show.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "`create_operation_approval` Params: ... `operation`: Name of the operation to be approved" (reason: contradicts src/permit_mcp/server.py; the tool takes user_id, reason, resource_instance only.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "`list_access_requests`: ... optionally filtered by approver or resource" and "`list_operation_approvals` ... (by user, role, or resource)" (reason: contradicts source; filters are status, role (access requests only), resource_instance, page, per_page.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: dependency list "`fastapi` ... `bcrypt`, `python-jose[cryptography]` ... `websockets`, `httpx`, `rich`" installed by `uv pip install -e .` in the repo root (reason: contradicts root pyproject.toml; those packages belong to examples/food-ordering-system/pyproject.toml. Same fix in the demo page's install info box.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "Permit.io handles much of this [logging of all tool interactions] by default" (reason: could not verify that access request or approval tool calls are logged; kept only that permission checks appear in the audit log.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "Frameworks like HumanLayer or Permit Elements UI can help with this." (reason: HumanLayer integration could not be verified; removed HumanLayer, kept the Permit Elements.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "Use Permit CLI's test generation features to simulate and validate scenarios." (reason: verified `permit test generate e2e` in /how-to/permit-cli/permit-cli-test; kept, reworded to name the command and link it. Note: the command generates RBAC tests by default; ReBAC coverage for this demo's model not verified.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "Each tool is fully compatible with LangChain, LangGraph, Claude Desktop, and other LLM systems that support function-calling agents." (reason: overclaim; reworded to MCP clients and frameworks that support MCP tools, with Claude Desktop and langchain-mcp-adapters as the verified examples.) -- `docs/ai-security/access-request-mcp/implementation-guide.mdx`: "`uv run server.py`" verification with "You should see output indicating that the server is running" (reason: from the repo root the path is wrong; source logs `Starting Permit MCP server...`. Page now says to run from src/permit_mcp, where the command works and load_dotenv finds the root .env.) -- `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx`: "Head to **Project Settings** in the Permit dashboard and collect: `PROJECT_ID`, `ENV_ID`, `PERMIT_API_KEY`, `PERMIT_PDP_URL`" (reason: could not verify the dashboard location; replaced with links to the owning pages.) -- `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx`: "`langchain-google-genai`: For interacting with Gemini 2.0 Flash" (reason: stale; gemini-2.0-flash shut down June 1, 2026 per ai.google.dev deprecations. Pinned models `gemini-2.0-flash` and `gemini-2.5-flash-preview-04-17` logged in codefix_w14.md; prose tells readers to check the models list.) -- `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx`: screenshots 1.png and 2.png show the role `child-can-order`, while the page and the FastAPI backend use `child-can-view` (reason: screenshots out of sync with the page. Kept, with a sentence telling the reader to name the role `child-can-view`; retake the two screenshots with `child-can-view`.) -- `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx`: "After running the client, the graph should not look like this:" (reason: wrong; 8.png shows the graph with human_review_node, which is the expected result. Rewritten as the verify step.) -- `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx`: "In this tutorial, you'll build a fully functional food-ordering system" and "Dynamically invoke MCP tools like `request_access`" (reason: `request_access` isn't a tool in the server; removed.) -- `docs/ai-security/access-request-mcp/overview.mdx`: "AI agents in regulated environments (e.g. SOC 2, HIPAA)" (reason: generalization with compliance names that reads as a compliance claim; removed.) -- `docs/ai-security/access-request-mcp/overview.mdx`: "the MCP server becomes the foundation for secure agent workflows" and "real-time interrupt/resume patterns" as a server feature (reason: hype; interrupt/resume is LangGraph behavior in the client, not a server feature.) -- `docs/ai-security/framework.mdx`: "Access on Behalf - Create traceable, auditable policies for actions made on behalf of human/AI users, with full decision-making chain visibility." (reason: could not verify "full decision-making chain visibility"; reworded to reviewing decisions in the audit log.) -- `docs/ai-security/framework.mdx`: "Compliance Policies - Use classification and access control to ensure AI-generated responses align with pre-determined policies." and "Framework Integration: use Permit's RAG security components in chain and agent frameworks" (reason: vague product claims; replaced with the checks the linked integration guides implement.) - -### Batch w15 (`ai-security/integrations` and related pages) - -- `docs/ai-security/integrations/langchain.mdx`: "By the end of this tutorial, you'll have a fully functional, policy-aware LangChain app ready for production." (reason: could not verify; retriever does not pass document key or attributes to filter_objects, and the example code does not run as written) -- `docs/ai-security/integrations/langchain.mdx`: "Only authorized users can view restricted documents." and expected table "Valid user | All documents (public + private)" (reason: no policy rule on the page grants view on non-public docs; contradicts the configured policy) -- `docs/ai-security/integrations/langchain.mdx`: "Scheduling Eligible Users" set used in rules but never created (added a creation step derived from the page's own model: user.age >= 18, user.can_schedule == true) -- `docs/ai-security/integrations/langchain.mdx`: "PermitEnsembleRetriever ... filter documents based on Permit's ABAC policies" (reason: contradicts langchain-permit 0.1.4 source; `_filter_by_permissions` sends `{"id","type"}` and permit-python `filter_objects` reads `key`/`attributes`, so `resource.public` never reaches the PDP. Replaced with a warning. Library bug to raise with owners.) -- `docs/ai-security/integrations/langchain.mdx`: "PERMIT_PDP_URL ... Or your cloud PDP" (reason: contradicts docs/concepts/pdp/cloud-pdp-capabilities.mdx; ABAC user sets need an Edge PDP. Prose now says Edge PDP; code comment logged) -- `docs/ai-security/integrations/langchain.mdx`: "Here are two examples based on the JWTs shown in the blog" (reason: meta reference to an external blog) -- `docs/ai-security/integrations/langchain.mdx`: "You can use the Policy Editor to tweak conditions and immediately affect runtime behavior." (reason: "immediately" unverified; replaced with "the PDP receives the updated policy and the next check uses it") -- `docs/ai-security/integrations/langchain.mdx`: "HIPAA-regulated phrases" as parser extension example (reason: vague compliance wording; replaced with patient names, medical record IDs, personal data) -- `docs/ai-security/integrations/langflow.mdx`: ":::tip Cloud PDP You can also point to the cloud PDP instead of running locally, by setting pdp_url to https://cloudpdp.api.permit.io" (reason: contradicts cloud-pdp-capabilities.mdx; the tutorial's policy is ABAC, which the Cloud PDP doesn't evaluate) -- `docs/ai-security/integrations/langflow.mdx`: "when multiple boxes are checked for an action, all conditions must be satisfied for the action to be allowed" (reason: contradicts Policy Editor semantics; each checked box is a separate grant. Owner should confirm) -- `docs/ai-security/integrations/langflow.mdx`: "Filter IDs (optional): List of specific booking records to restrict" on Data Protection (reason: contradicts source; permit-langflow-framework `components/data_protection.py` has no filter_ids input, only the README mentions it) -- `docs/ai-security/integrations/langflow.mdx`: "Use test JWT tokens with embedded attributes to simulate different user roles" (reason: contradicts source; JWT Validator outputs only `sub`, Permissions Check sends no attributes. Page now says to store attributes on the user in Permit) -- `docs/ai-security/integrations/langflow.mdx`: expected behavior matrix "Basic Tier: Search ✅ Limited area; Info ✅ Public info" and "tier: basic, region: international ❌ Might be restricted" (reason: not derivable from the policy in screenshot 8.jpg; replaced with results computed from that policy, with `info` checked for Regional Restrictions because the screenshot grants `info` to no user set) -- `docs/ai-security/integrations/langflow.mdx`: screenshot `/img/ai-security/integrations/langflow/10.png` reused under the Flight Booking flow "Flow Connections" (reason: the screenshot shows the Flight Information flow with Permissions Check action `info` on `flight`; removed from the booking section, kept in the information section) -- `docs/ai-security/integrations/langflow.mdx`: "Or use Langflow Cloud (https://www.langflow.org/) to import your flows via JSON" (reason: could not verify a Langflow Cloud import path; no flows JSON is provided for this tutorial) -- `docs/ai-security/integrations/langflow.mdx`: "you can ship secure, compliant AI systems without writing custom enforcement logic from scratch" and "Keep AI workflows safe and compliant" (reason: unverifiable compliance/security claim) -- `docs/ai-security/integrations/langflow.mdx`: fake endpoints `https://api.flightpolicies.com/baggage`, `https://api.flightpolicies.com/services`, `https://api.flights.com/v1/bookings` in prose (reason: third-party-looking domains presented as example APIs; replaced with placeholders) -- `docs/ai-security/integrations/langflow.mdx`: "Github: langchain-permit" as the Langflow resource (reason: wrong repo; the Langflow components are in permitio/permit-langflow-framework) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "Role-Based Access Control (ReBAC)" (reason: wrong expansion; ReBAC is relationship-based) -- `docs/ai-security/integrations/mongodb-rag.mdx`: manual setup "Role: viewer (permission: document:read)" and role assignments of `viewer` (reason: contradicts repo scripts; the model uses `department#member`, `document#reader`, and a derivation through `parent`) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "Run setup_users.py to create users (alice, bob)" (reason: contradicts scripts/setup_users.py, which creates user_engineering_1, user_engineering_2, user_marketing_1, user_finance_1) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "After running these scripts, you'll only need to define the role derivation manually in the Permit.io UI" (reason: contradicts scripts/setup_rebac.py, which calls create_role_derivation) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "Update the file_path in sync_documents.py to the document you want to sync" (reason: stale; `__main__` runs sync_all_documents over ./docs) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "`carol` → `user_marketing_1` (viewer in marketing)" (reason: role is `member`, not viewer) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "Immediate RAG Availability: Newly added files are ... immediately available for RAG queries" (reason: "immediately" unverified; watcher syncs to MongoDB, but Permit document instances are created only by permit-sync at startup or by running sync_documents.py) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "In your cluster ... (e.g., AWS Singapore)" region example (reason: irrelevant volatile detail) -- `docs/ai-security/integrations/mongodb-rag.mdx`: "This ensures that sensitive data is only accessible to authorized users, making the RAG system secure." (reason: vague security claim; the `confidential` attribute is synced but no rule uses it) -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: "we're using the Container PDP because: It supports our role-based permissions" (reason: contradicts cloud-pdp-capabilities.mdx; Cloud PDP supports RBAC. The container PDP is needed because the resource sets are ABAC) -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: "It provides faster response times for local development" / "It allows offline development and testing" (reason: could not verify "offline"; the PDP still syncs policy from the control plane. Kept only "no network round trip to the Cloud PDP") -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: "Go to Directory → Roles" (reason: contradicts screenshot 2.png; roles are under Policy > Roles) -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: "If the user lacks the ai_advisor or opted_in flag" (reason: no `opted_in` attribute in this model; access is by the `ai_advisor` role) -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: "dynamically adapts to the user's intent—no hardcoded rules, or brittle endpoint matching", "Handles ambiguous or implicit requests gracefully", "Zero Hardcoding" (reason: marketing phrasing; added that an LLM classifier can misclassify) -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: "especially useful for ... compliance reviews" and "Evaluated roles and attributes / Matched conditions and resource sets" as audit log contents (reason: could not verify which fields the audit log shows; reduced to user, action, resource, decision) -- `docs/ai-security/integrations/openai-prompt-filtering.mdx`: broken link `https://www.app.permit.io/` (reason: invalid host; replaced with https://app.permit.io/) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "The full source code ... is available here: Secure Financial Advisor AI Agent (https://github.com/permitio/langchain-permit)" (reason: wrong repo; source is permitio/Permit-PydanticAI) -- `docs/ai-security/integrations/pydantic-ai.mdx`: PydanticAI link `https://github.com/eylonper/pydantic-ai` (reason: personal fork, returns 404; replaced with https://github.com/pydantic/pydantic-ai) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "running the config.py file ... creates: All required resources, attributes, and roles; Sample condition and resource sets; A usable policy matrix with attached rules" (reason: contradicts example/config.py; `create_permit_config` doesn't create users, role assignments, or condition set rules) -- `docs/ai-security/integrations/pydantic-ai.mdx`: attribute model `opted_in`, `role`, `clearance_level: low/high/medium/none/confidential`, `membership_tier`, `verified` (reason: contradicts example/config.py, which defines `clearance_level` (low, high) and `ai_advice_opted_in`) -- `docs/ai-security/integrations/pydantic-ai.mdx`: expected tables with Alice/Bob/Carol/Dave and `clearance: medium` → `restricted` ✅ (reason: users and rules not defined anywhere; replaced with the two example users from config.py and results derived from its roles) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "Real-World Scenarios: membership: premium, verified: true/false" (reason: attributes don't exist in the example; portfolio access is by `premium_user` role) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "Result: Blocked from advice, sensitive documents, and bookings." (reason: "bookings" copied from the flight demo; no booking resource) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "this perimeter gives you full confidence that every answer shown to your users is policy-compliant" and "lightweight but powerful enforcement check" (reason: unverifiable/marketing) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "Premium User: Ask for financial advice ✅ Allowed (with disclaimer)" (reason: config.py grants no role `requires_disclaimer` on `financial_response`, so the disclaimer check is denied; page now tells readers to grant it) -- `docs/ai-security/integrations/pydantic-ai.mdx`: "You may also use the cloud PDP by setting PDP_URL=https://cloudpdp.api.permit.io" (reason: contradicts cloud-pdp-capabilities.mdx; policy is ABAC) -- All five pages: Slack link `https://io.permit.io/blog-slack` (reason: style guide requires https://io.permit.io/slack) - -### Batch w16 (`integrations/gateways` and related pages) - -#### Product issues found (coordinator: escalate to PDP owners) - -- `docs/integrations/gateways/kong.mdx`: the documented Kong flow ("configure the Kong OPA plugin to call the PDP at /kong") (reason: contradicts permitio/PDP main and v0.9.15. `horizon/pdp.py` mounts the enforcer router, which includes `/kong`, with `Depends(enforce_pdp_token)`; `horizon/tests/test_enforcer_api.py` lists `/kong` in `PROTECTED_ENFORCER_ENDPOINTS` and asserts 401 without `Authorization: Bearer ` (PR #317, "gate /kong ... enforce PDP token at router level", 2026-07-08). The Kong OPA plugin config reference (developer.konghq.com/plugins/opa/reference) has no header field, and Kong returns 500 when OPA responds non-200. Page keeps the steps and adds a danger admonition stating these facts.) -- `docs/integrations/gateways/nginx.mdx`: the implied claim that the auth_request setup blocks requests the policy denies (reason: contradicts permitio/PDP `horizon/enforcer/api.py` `is_allowed_nginx`: route is `@router.post("/nginx_allowed", status_code=200)` and returns `{"allow": false}` with HTTP 200; nginx auth_request denies only on 401/403. The route is POST-only and token-gated. Page keeps the steps and adds a danger admonition.) - -#### Removed or reworded claims - -- `docs/integrations/gateways/kong.mdx`: "continue to make decisions extremely quickly, on the order of 1-5 ms" (reason: could not verify; not in owner-confirmed figures) -- `docs/integrations/gateways/kong.mdx`: "With a recent update - Permit can now seamlessly integrate with Kong Gateway ... within minutes without having to write a single line of code" (reason: dated wording and hype) -- `docs/integrations/gateways/kong.mdx`: "it's completely independent (so it keeps running even if disconnected from the Internet)" (reason: not verified for this page; replaced with "evaluates checks locally with the policy it has received") -- `docs/integrations/gateways/kong.mdx`: "click Copy SDK secret key from your user profile" and screenshot `/img/updated/kong/kong-1.png` (reason: stale UI label, dashboard term is API key per /overview/get-api-key; the screenshot also shows a real employee's name and email. Replaced with a link to /overview/get-api-key.) -- `docs/integrations/gateways/kong.mdx`: "a nice user interface that is easy to understand for everybody in your organization", "empower non technical people" (reason: marketing) -- `docs/integrations/gateways/kong.mdx` added facts (verified): user = Kong consumer username, action = lowercase HTTP method, tenant = `default`, resource from `/config/kong_routes.json` (default rules `/v\d+/([^/]+).*`, `/([^/]+).*`, `/` -> `index`), 503 when `PDP_KONG_INTEGRATION` is off, deny when no consumer or no route match (source: permitio/PDP `horizon/enforcer/api.py`, `kong_routes.json`, `Dockerfile`). Kong OPA plugin Enterprise tier and 403 on deny (source: developer.konghq.com/plugins/opa). -- `docs/integrations/gateways/overview.mdx`: "If you are using AWS Cedar as your policy engine in Permit, you'll have to configure the HTTP filtering with the PDP manually, as there are no cloud-native proxy/gateway plugins available yet" (reason: roadmap wording; Cedar in the Permit PDP image could not be verified: permitio/PDP main has no Cedar references) -- `docs/integrations/gateways/overview.mdx`: "This approach can be easily implemented with plugins from the OPA Plugin System with minimal configuration" (reason: hype; OPA plugin applies to Kong only among documented integrations) -- `docs/integrations/gateways/overview.mdx`: "This ensures data consistency, security, and low latency" / "cloud-native architecture of the Permit PDP ensures that the decision is made with low latency" (reason: vague; reworded to the mechanism: requests stay in your network and avoid a round trip) -- `docs/integrations/gateways/overview.mdx`: "the first option is more efficient" (reason: unverified comparison; kept as "works with your existing Permit policy" vs "takes more development and maintenance") -- `docs/integrations/gateways/overview.mdx`: Slack link `https://io.permit.io/blog-slack` (reason: style guide Slack URL is https://io.permit.io/slack) -- `docs/integrations/gateways/aws-api-gateway.mdx`: "we will use the HTTP API in this example" (reason: contradicts the steps and screenshots, which show the REST API console: Resources menu, Create method, Token/Request payload. Page now says REST API.) -- `docs/integrations/gateways/aws-api-gateway.mdx`: "specifically the `permit.Check()` method" (reason: the Python SDK method is `check` (permit-python `permit/enforcement/enforcer.py` `async def check`)) -- `docs/integrations/gateways/aws-api-gateway.mdx`: "You can use the Test tab ... and see the response from the Lambda function" (reason: replaced by authorizer Test with expected Allow/Deny policy, which depends on the logged code fix) -- `docs/integrations/gateways/aws-api-gateway.mdx`: "to reduce latency and improve security" (reason: vague; reworded to "so checks don't leave your network") -- `docs/integrations/gateways/nginx.mdx`: "Regularly update Nginx and Permit.io components", "Implement proper rate limiting and DDoS protection", "Consider caching authorization results" (reason: generic advice, not specific to the integration) -- `docs/integrations/gateways/nginx.mdx`: audit link `https://app.permit.io/audit` and Slack invite `permit-io.slack.com/join/shared_invite/...` (reason: stale; replaced with https://app.permit.io/audit-log as used in how-to/use-audit-logs/types-and-filtering.mdx, and https://io.permit.io/slack) -- `docs/integrations/GraphQL/overview.mdx`: "With Permit it becomes effortless", "commit a terrible sin", "think twice ;-)" (reason: hype and tone) -- `docs/integrations/GraphQL/overview.mdx`: "This way is more scalable and easier to maintain" for directives (reason: unsupported comparison; reworded to trade-offs) -- `docs/integrations/GraphQL/overview.mdx`: implied that `@permit` is an available directive (reason: no Permit package provides a GraphQL `@permit` directive that I could find; page now says your server implements it) -- `docs/integrations/GraphQL/apollo_server.mdx`: "go to Permit's connect SDK screen ... (steps 1-3)" (kept as a pointer, UI screen not re-verified) -- `docs/integrations/GraphQL/apollo_server.mdx`: verify step "The response contains the `Not allowed` error" (reason: Apollo Server 3 error response shape for errors thrown in `requestDidStart` not verified against source; wording kept general) -- `docs/integrations/SCIM/SCIM_overview.mdx`: "Developed in 2011", benefit bullets "Efficiency ... without manual intervention", "Error Reduction", "Security: Reduces risks by ensuring users don't need multiple passwords", "providing seamless access" (reason: generic marketing claims; replaced with mechanism-based bullets) -- `docs/integrations/SCIM/EntraID.mdx`: link `/overview/connecting-your-app#1-get-your-permit-environment-api-key` and "Permit API Key" (reason: cross-page finding; now /overview/get-api-key and "API key") -- `docs/integrations/SCIM/EntraID.mdx`: "the user has been successfully created !" and provisioning log "status" (reason: screenshot 9 shows an Action column, not a status; verify step reworded to what the screenshot shows) -- `docs/integrations/SCIM/OKTA.mdx`: screenshot `dashboard-1.jpeg` shows Base URL host `permit-scim-okta.permit.io`, which differs from the documented `scim.permit.io` (reason: stale screenshot; kept with neutral alt text, needs a retake). Screenshot `https://i.imgur.com/KRZCbiw.png` is hosted on imgur (maintenance risk; kept). -- `docs/integrations/SCIM/OKTA.mdx`: "Enjoy the seamless integration" (reason: hype) -- `docs/integrations/SCIM/*`: SCIM endpoint URLs are not in the Permit API spec (openapi.json has no SCIM paths). Kept: `https://scim.permit.io/scim/v2/p/e/Users`, `.../p/e/v2/t1/Users`, and the `scim.eu-central-1.permit.io` host all answer with a SCIM-format 401 error, so the hosts and path shapes exist. -- `docs/integrations/policy-engines/overview.mdx`: "Permit.io, unlike other permission services, supports multiple policy engines" (reason: competitive claim, unverifiable) -- `docs/integrations/policy-engines/overview.mdx`: "Cedar agent is the easiest way to deploy and run Cedar" (reason: hype, even though the cedar-agent repo description says it) -- `docs/integrations/policy-engines/overview.mdx`: "We continually evaluate additional policy languages and engines ... follow updates or suggest the next integration" (reason: roadmap wording; replaced with a Slack pointer) -- `docs/integrations/policy-engines/overview.mdx`: implied claim that the Permit PDP image runs Cedar (reason: could not verify; permitio/PDP main has no Cedar references. Page says the Permit PDP runs OPA, and that the OPAL client can run Cedar-agent (verified: permitio/opal `opal_client/config.py` `INLINE_CEDAR_ENABLED`, `engine/runner.py` `CedarRunner`). Other pages still say Permit supports Cedar: faq.mdx, overview/glossary.mdx, overview/how-does-it-work.mdx, how-to/build-policies/policy-basics.mdx, concepts/pdp/configuration.mdx `OPAL_INLINE_CEDAR_ENABLED`; owner should confirm.) - -### Batch w17 (`integrations/gitops` and related pages) - -- `docs/integrations/gitops/overview.mdx`: "The feature is available **in trial** to all Permit users as a self-service" (reason: stale; www.permit.io/pricing lists "Git Policy Storage" and "Sync Policies to Your Own Git" on all plans. Replaced with a link to the pricing page, no plan claim in the docs) -- `docs/integrations/gitops/overview.mdx`: "improved consistency, accuracy, and traceability ... reduce the risk of unauthorized access" (reason: generic benefit claims; replaced with mechanism-level statements: commit history, review, same code per environment) -- `docs/integrations/gitops/overview.mdx`, `github.mdx`, `custom_policy.mdx`: added "Cloud PDP doesn't run custom Rego" (reason: added from docs/concepts/pdp/cloud-pdp-capabilities.mdx, "Custom policy as code (custom Rego through GitOps): Not supported" on Cloud PDP) -- `docs/integrations/gitops/github.mdx`: "custom/root.rego" vs custom_policy's "custom.rego" (reason: contradiction resolved in favor of `custom/root.rego` (package permit.custom), verified in permitio/generated-policy-example, permitio/permit-backend v2/policy_synchronizer/tests/pdp_policy/custom/root.rego, and customer policy repos' .manifest files. custom_policy.mdx prose updated; both pages now say custom code goes in the `custom` folder and the only documented edit outside it is combining `allow` rules in top-level `root.rego`, which the generated root.rego comments describe) -- `docs/integrations/gitops/github.mdx` + `custom_policy.mdx`: "avoid editing policy code outside of this folder, as it could potentially be overridden by our code" (reason: kept as a warning but NOT verified whether Policy Sync regenerates the top-level `root.rego`; permit-backend git_interface.py only whitelists paths containing "custom", "rebac", "user_permissions" when resolving merge conflicts. custom_policy.mdx now tells readers to confirm their root.rego change is still present after dashboard changes. Owner should confirm) -- `docs/integrations/gitops/github.mdx`: "Make sure the deploy key is set up without Two-Factor Authentication (2FA) to allow the Permit server unrestricted read and write access" (reason: GitHub deploy keys have no 2FA setting; removed) -- `docs/integrations/gitops/github.mdx`: tip linking a personal gist `gist.github.com/ocap-kirk/...` as the automated script (reason: personal account link; replaced with the official `permit gitops create github` CLI wizard documented in how-to/permit-cli/permit-cli-gitops.mdx) -- `docs/integrations/gitops/github.mdx`: "your private key will be securely stored on our end, and no passphrase will be required" (reason: storage-security claim unverified; replaced with the verified fact that the API's SSHAuthData schema has no passphrase field) -- `docs/integrations/gitops/github.mdx`: added verify step with `GET /v2/projects/{proj_id}/repos/active` and status values pending/valid/invalid (reason: verified in api.permit.io/v2/openapi.json PolicyRepoRead/PolicyRepoStatus) -- `docs/integrations/gitops/custom_policy.mdx`: "Permit.io supports two open-source policy engines: OPA, and Cedar ... Each engine has a Policy language" (reason: Cedar support as a PDP engine is documented in integrations/policy-engines/overview.mdx and faq.mdx; custom GitOps code in Cedar is not verified. Reworded to "The PDP can also run AWS Cedar as its engine" with a link; the guide covers Rego only) -- `docs/integrations/gitops/custom_policy.mdx`: "you can set a meeting with our engineering team. Were always happy to help" (reason: replaced with Slack community and https://www.permit.io/demo per style guide) -- `docs/integrations/gitops/custom_policy.mdx`: repository layout table (reason: based on permitio/generated-policy-example tree: root.rego (permit.root), permit/, rbac.rego, abac.rego, custom/root.rego (permit.custom); layout of current generated repos may differ slightly) -- `docs/integrations/infra-as-code/terraform-provider.mdx`: "**Enhanced Features**: Some additional features and improvements over Terraform" and the whole "Benefits of Using OpenTofu" list (reason: unverified third-party marketing claims; removed) -- `docs/integrations/infra-as-code/terraform-provider.mdx`: `version = "~> 0.0.14"` (reason: stale pin; latest release of permitio/terraform-provider-permit-io is v0.0.25 (2026-07-15). Prose explains the constraint accepts 0.0.14+ and links the registry; code change logged in codefix_w17.md. Note the repo is terraform-provider-permit-io, not terraform-provider-permitio) -- `docs/integrations/infra-as-code/terraform-provider.mdx`: "Terraform will automatically use the environment variables" (reason: verified in internal/provider/provider.go: PERMITIO_API_KEY, PERMITIO_API_URL, PERMITIO_TIMEOUT) -- `docs/integrations/infra-as-code/terraform-provider.mdx`: "Ensure you're using an environment-level API key, not a workspace-level key; Verify the API key has the correct permissions" (reason: kept in the troubleshooting table as "use the API key of the environment you manage"; not verified against provider behavior) -- `docs/integrations/infra-as-code/terraform-provider.mdx`: "Use Workspaces for Environment Separation" (reason: misleading without per-workspace API keys; added a warning that the workspace doesn't change the API key) -- `docs/integrations/infra-as-code/terraform-provider.mdx`: `apt-get install opentofu` / `dnf install opentofu` (reason: need the OpenTofu package repository first; prose note added and linked to OpenTofu install docs) -- `docs/integrations/feature-flagging/casl.mdx`: "the `permit-fe-sdk` fully supports version 6 of CASL" (reason: could not verify; permit-fe-sdk has no CASL dependency and its README links CASL v5 docs; removed. The SDK outputs {action, subject, inverted} rules consumed by `new Ability()`) -- `docs/integrations/feature-flagging/casl.mdx`: "Permit is designed to integrate seamlessly with all [authentication providers]" (reason: hype; replaced with "Any authentication provider works if it gives you the ID of the signed-in user") -- `docs/integrations/feature-flagging/casl.mdx`: garbage text "q1 1§1" (reason: removed) -- `docs/integrations/feature-flagging/casl.mdx`: links to `/overview/connecting-your-app#1-get-your-permit-environment-api-key` and `#2-setup-your-pdp-policy-decision-point-container` (reason: replaced with /overview/get-api-key and /overview/run-pdp) -- `docs/integrations/feature-flagging/casl.mdx`: added "loadLocalStateBulk() runs its request only once per page load" and "permitState.check() returns false for items not loaded" (reason: verified in permit-fe-sdk src/index.ts: isInitialized guard, defaultAnswerIfNotExist = false) -- `docs/integrations/feature-flagging/casl.mdx`: added warning that frontend checks don't protect data (reason: general security fact, no product claim) -- `docs/integrations/workflow-automation/n8n.mdx`: "Cloud PDP supports RBAC workflows" and "Local PDP container for ABAC/ReBAC policies (optional but recommended)" (reason: contradicts cloud-pdp-capabilities.mdx, which lists RBAC and ReBAC as supported and ABAC as not supported on Cloud PDP; reworded) -- `docs/integrations/workflow-automation/n8n.mdx`: "use a local PDP container for better performance and advanced policy support" (reason: performance claim unverified; kept only the ABAC requirement) -- `docs/integrations/workflow-automation/n8n.mdx`: "**Response:** `{"error": "Access denied", "reason": "Exceeds spending limit"}`" (reason: invented; the denied branch returns whatever the user configures in the Respond to Webhook node, per the workflow screenshot; replaced with that description) -- `docs/integrations/workflow-automation/n8n.mdx`: "The node automatically extracts attributes from webhook payloads when Enable ABAC is checked" (reason: imprecise; Permit.node.ts sends `items[i].json.body` as resource attributes, so every body field becomes a resource attribute. Page now says so) -- `docs/integrations/workflow-automation/n8n.mdx`: "transforms how you handle authorization ... Seamlessly extracting context ... intelligent access control decisions ... scales with your organization" (reason: hype; removed) -- `docs/integrations/workflow-automation/n8n.mdx`: node field names and operation names (reason: verified against permitio/n8n-nodes-permitio nodes/Permit/Permit.node.ts and credentials/PermitApi.credentials.ts; label "Resource Attributes (JSON)" corrected) -- `docs/integrations/workflow-automation/n8n.mdx`: "n8n Cloud can't reach localhost or a private network ... expose the PDP at a public HTTPS address" (reason: from the n8n-nodes-permitio README, which suggests exposing the PDP publicly, e.g. ngrok; "restrict who can reach that address" added as a security instruction) - -### Batch w18 (`how-to/policy-guard` and related pages) - -- `docs/how-to/policy-guard/policy_guard.mdx`: "Currently, Policy Guards are accessible only via the Permit API. The Policy Guard UI is on the roadmap, message us in our slack channel `#early-access-program` to get early access yourself." (reason: roadmap/dated wording and early-access ask; removed. Page says Policy Guards are managed with the API, listed under the "Policy Guards (EAP)" tag in the OpenAPI spec) -- `docs/how-to/policy-guard/policy_guard.mdx`: "ReBAC (Relationship-Based Access Control) support is on the roadmap" (reason: roadmap wording; replaced with verified fact from permitio/permit-backend schemas/schema_policy_guard_rule.py and general_tasks/policy_guard.py: rules take role_key (a top-level tenant role), user_set, resource_set; no field for ReBAC resource roles or relationships) -- `docs/how-to/policy-guard/policy_guard.mdx`: "Only a workspace Owner can add or remove new guarding policy rules." (reason: contradicts source. permit-backend authz.py `_check_or_http_policy_guard` checks org-admin grant, and ForbiddenOrgAdminPolicyGuardException says "This API Requires an Organization API Key or workspace admin permissions"; applies to all scope, association, and rule endpoints. Page now says organization API key or Workspace Owner. Mapping of MemberAccessLevel.ADMIN on ORG to the UI label "Workspace Owner" is inferred, not verified in the frontend) -- `docs/how-to/policy-guard/policy_guard.mdx`: two images `/img/policy-guard/lock.png` and `/img/policy-guard/scope.png` (reason: both are mockups of an unreleased Policy Guard UI; lock.png carries a banner "Conceptual PREVIEW, Currently available ONLY AS API". Removed as describing an unreleased feature. diagram.png kept) -- `docs/how-to/policy-guard/policy_guard.mdx`: "helps maintain a high level of security and access control", "Audit and Compliance ... easy auditing and compliance checks" (reason: generic unsupported claims; replaced with the mechanism: list a scope's rules with the API) -- `docs/how-to/policy-guard/policy_guard.mdx`: added "In a guarded environment, a change to a permission that a Policy Guard rule covers fails with a 403 Forbidden error" (reason: verified in permit-backend authz.py check_or_http_exception -> ForbiddenPolicyGuardException; exact set of guarded object edits not exhaustively verified) -- `docs/how-to/policy-guard/policy_guard_api.mdx`: "If you need to remove a policy guard scope, you can delete it by specifying its ID. This will remove all associated permissions and roles." (reason: could not verify; routers/policy_guards.py delete route only deletes the scope and logs; removed) -- `docs/how-to/policy-guard/policy_guard_api.mdx`: "you can disassociate it ... This will remove the project's permissions defined in the scope." (reason: contradicts source; disassociate deletes the scope detail and sets the project's environments is_guarded=false, it does not remove permissions. Page now says the environments are no longer guarded) -- `docs/how-to/policy-guard/policy_guard_api.mdx`: added response facts (task object with task_id/status and `wait` query param on associate and rule create; 204 on deletes; 404 when no rule matches; conflict on duplicate rule; 400 for role_key + user_set without resource_set) (reason: verified against openapi.json and permit-backend routers/policy_guards.py, services/policy_guard_rules.py, migration b4cbc03b8324 check constraint) -- `docs/integrations/database-access-control/trino-integration.mdx`: "Trino does not currently support passing an API key or credentials when calling external authorization endpoints." (reason: dated wording; kept without "currently", linked Trino issue 27022) -- `docs/integrations/database-access-control/trino-integration.mdx`: "If Trino cannot reach the PDP or the PDP errors, Trino denies the query." (reason: only the PDP side is verified: PDP checks.rs returns false on OPA error. Trino-side behavior when the PDP is unreachable not verified; sentence now covers only the PDP side) -- `docs/integrations/database-access-control/trino-integration.mdx`: "Procedure ... Resource Name: `trino_procedure___`" (reason: contradicts source. Trino OpaAccessControl.checkCanExecuteProcedure sends the procedure as a `function` resource, and PDP pdp-server/src/api/trino/checks.rs maps it to `trino_function___`; the PDP has no procedure resource. Mapping table updated. NOTE for owner: permit-cli source/utils/trinoUtils.ts creates `trino_procedure_*` and `trino_view_*`/`trino_materialized_view_*` resources, which the PDP never checks, since views are sent as table resources) -- `docs/integrations/database-access-control/trino-integration.mdx`: "Masks return only when the user (or role) has the corresponding Permit action." (reason: refined from PDP column_mask.rs and trino-authz.example.yaml: mask applies when the user has the action on the table resource OR the column resource; per-column `action` override and default `AddColumnMask` documented) -- `docs/integrations/database-access-control/trino-integration.mdx`: "Test queries as different users and confirm audit entries appear both in Permit and Trino." (reason: Trino has no audit entries; replaced with Trino server log output from opa.log-requests/opa.log-responses) -- `docs/integrations/database-access-control/trino-integration.mdx`: "Centralize database-level permission logic with Permit's Policy Builder", "Enforce the decision before data leaves your database", "most effective for organizations that..." (reason: marketing/unsupported phrasing; replaced with mechanism-based capability list) -- `docs/integrations/database-access-control/trino-integration.mdx`: added "If the file is missing or fails to parse, the PDP starts without row filters and column masks" and "If a column is listed twice, the PDP keeps the first entry" (reason: verified in PDP pdp-server/src/config/trino_authz.rs) -- `docs/integrations/permit-mcp/overview.mdx`: server.py link "https://github.com/Tammibriggs/permit-mcp/blob/main/examples/food-ordering-system/server.py" (reason: personal fork; `gh search repos --owner permitio mcp` shows permitio/permit-mcp, which has examples/food-ordering-system/server.py. Link changed to the permitio repo. Note: permitio/permit-mcp last push 2025-05-05) -- `docs/integrations/permit-mcp/overview.mdx`: model "gemini-2.5-flash-preview-04-17" pinned in code (reason: volatile preview model version; the same pin is in permitio/permit-mcp server.py. Code unchanged, logged in codefix_w18.md; page adds a note to switch to a current model on a model-not-found error) -- `docs/integrations/permit-mcp/overview.mdx`: "Currently, family members cannot order dishes or even list the available dishes" (reason: dated wording; reworded to what the Permit MCP server tools cover) -- `docs/integrations/permit-mcp/overview.mdx`: "A resource called `restaurant`" (reason: contradicts the code and screenshots, which use `restaurants`; fixed) -- `docs/integrations/permit-mcp/overview.mdx`: added verify flow (child denied by list_dishes, access request, parent approves, child can list dishes) (reason: derived from permitio/permit-mcp food_ordering_mcp.py and utils.py init_db role assignments; not run end to end, and the assistant's replies depend on the LLM) -- `docs/integrations/permit-mcp/overview.mdx`: "In this project we are using the local Permit PDP instead of Cloud PDP primarily for network and operational control reasons" (reason: kept as the design choice; docs/concepts/pdp/cloud-pdp-capabilities.mdx lists ReBAC as supported on Cloud PDP, so no ReBAC requirement was claimed) - -### Batch w19 (`modeling/mesa-verde.mdx` and related pages) - -- `docs/modeling/mesa-verde.mdx`: "Implementing this flow from scratch can take a long time, but with Permit.io, you can do it in minutes" (reason: unverifiable time claim; removed) -- `docs/modeling/mesa-verde.mdx`: "a balance check is a basic operation that can be added to the flow in minutes" (reason: unverifiable time claim; replaced with the fact that the demo doesn't check balance) -- `docs/modeling/mesa-verde.mdx`: "this intuitive demo should help you better understand..." / "enjoying the components' customization capabilities" / "see how easy it is" (reason: marketing wording; removed) -- `docs/modeling/mesa-verde.mdx`: "Only account owners can add members and beneficiaries to the account." (reason: contradicts main.tf, where AccountBeneficiary also has Account:add-members; corrected) -- `docs/modeling/mesa-verde.mdx`: "Wire Transfer#_Approved_ is the role assigned to a user who requests approval for a wire transfer" (reason: contradicts docs/embeddable-uis/element/operation-approval.mdx; Permit assigns _Approved_ after a reviewer approves; corrected) -- `docs/modeling/mesa-verde.mdx`: "Unsafe Owners ... or users that still have not verified their location" (reason: main.tf condition is only user.location not-equals user.country plus AccountOwner role; clause removed) -- `docs/modeling/mesa-verde.mdx`: "Strong Auth Users are users that we can't locate in their location but who provided a strong authentication method" (reason: main.tf user set is Strong_Auth_Owners = AccountOwner role and strongAuth true, no location condition; corrected) -- `docs/modeling/mesa-verde.mdx`: "external data sources (a dummy identity provider) to determine user operation anomalies" (reason: repo shows JSONBin stores country and middleware resolves IP location via ipinfo.io; reworded to mechanism) -- `docs/modeling/mesa-verde.mdx`: "the Permit policy as code engine generates it in Policy Languages such as Rego or Cedar and pushes it to a Git repository" (reason: could not verify Cedar generation or automatic push without GitOps configured; reworded to link GitOps) -- `docs/modeling/mesa-verde.mdx`: "we use events from the authentication provider (Stytch) to call the Permit's role assignment and create tenant APIs" (kept, reworded; repo syncUser in lib/permit.ts runs on first login, exact Stytch event not verified) -- `docs/modeling/mesa-verde.mdx`: "In our application, we are allowing Account Member users to request the Account Beneficiary role" (kept from original and its screenshot; setup.js roles_to_levels for the access request element is empty, so the requested role comes from the dashboard configuration and was not verified in code) -- `docs/modeling/mesa-verde.mdx`: link to blog "announcing-permit-share-if" and "Google-Zanzibar-like graph database" for transactions (reason: marketing link and unverified storage claim; removed, replaced with resource instances and resource roles description) -- `docs/modeling/google-drive.mdx`: "That second port (8081) is optional. You can use it if you want to interact directly with the OPA instance running within the PDP." (reason: contradicts permitio/PDP Dockerfile, which exposes OPA on 8181, not 8081; removed) -- `docs/modeling/google-drive.mdx`: "US West" / "US East" tab labels (reason: api.us-west/us-east/us .permit.io hosts don't resolve (curl -sI); PDP image default PDP_CONTROL_PLANE is https://api.permit.io per PDP Dockerfile line 286, so both tabs target the same control plane; relabeled and explained; EU base URL api.eu.permit.io taken from docs/api/api-reference.mdx) -- `docs/modeling/google-drive.mdx`: "To install the latest Java SDK you'll need version `2.0.0`." (reason: stale pin, and page has no Java samples; reworded to point to the Java quickstart for the current version) -- `docs/modeling/google-drive.mdx`: "Permit will assume such instance exists on your end and create it implicitly" (kept as "Permit creates the resource instance"; not re-verified against backend source) - -### Batch w20 (`modeling/feature-flagging.mdx` and related pages) - -- `docs/modeling/feature-flagging.mdx`: "A significant advantage of ABAC is its ability to dynamically utilize attributes from the user's Identity Provider (IDP) without the need for syncing this information ... enhancing both security and efficiency" (reason: overstated; reworded to the verified mechanism, JIT attributes passed in permit.check() per /how-to/enforce-permissions/check, and noted that the user and role assignment must still exist in Permit) -- `docs/modeling/feature-flagging.mdx`: "An authentication provider of your choosing (we support them all)" and "Permit is designed to integrate seamlessly with all of them" (reason: unverifiable universal claim; replaced with "any provider works if your app can read the user's ID and attributes") -- `docs/modeling/feature-flagging.mdx`: image sections "The UI" / "The Permit Policy" had swapped images (feature-flagging-1/3 are policy tables, -2/-4 are dashboards) (reason: contradicts the screenshots; images reordered under correct headings, anchors kept) -- `docs/modeling/feature-flagging.mdx`: implication that the shown policy is attribute-driven (reason: screenshots show only role toggles for Viewer; page now says to add user/resource sets on the ABAC Rules tab to make tiles depend on country/channel) -- `docs/modeling/food-delivery-system-example-using-nuxt.mdx`: "To deliver an order: User must have the rider role (RBAC), Order must be assigned to them (ReBAC), For free delivery orders, a rider must have 500+ rides (ABAC)" as an AND of all three (reason: could not verify; Permit grants from roles, instance roles, and condition sets combine with OR, and the app's middleware runs a type-level role check plus an instance check; reworded to describe the rules and checks without claiming AND semantics) -- `docs/modeling/food-delivery-system-example-using-nuxt.mdx`: "Fulfilling and Delivering orders won't work until we configure our ReBAC policies" (reason: could not verify; the RBAC vendor/rider grants on Order apply to all instances; removed) -- `docs/modeling/food-delivery-system-example-using-nuxt.mdx`: test steps "Check that vendors can only fulfill their own orders", "Confirm that riders can only deliver assigned orders", "Verify that riders with 500+ rides can deliver free delivery orders" (reason: negative outcomes unverified for the same OR-semantics reason; removed from the expected-result table, owner should confirm the intended policy) -- `docs/modeling/food-delivery-system-example-using-nuxt.mdx`: "toggle the create-with-free-delivery action on 'Order' by customers" (reason: changed to grant on the cost >= 500 resource set, which the stated rule requires; exact grant in the repo GIF not verified) -- `docs/modeling/food-delivery-system-example-using-nuxt.mdx`: "In the ABAC Rules tab" vs "In the ABAC Sets tab" (reason: inconsistent; unified on "ABAC Rules" per dashboard screenshots in feature-flagging and other docs) -- `docs/modeling/other-code-examples.mdx`: "Permit.io simplifies implementing fine-grained access control by providing powerful tools ... seamless integration" (reason: marketing language; replaced with a factual list of what the example repos cover, derived from the GitHub search query in src/components/GitHubExamples.jsx) -- `docs/modeling/pink-mobile.mdx`: "the control plane (the configuration of the rules), the data plane (the data that helps us make decisions), and the enforcement plane" (reason: contradicts glossary; control plane runs in Permit's cloud, data plane (PDPs) in your network; reframed as policy model / authorization data / enforcement and linked to /concepts/control-plane-and-data-plane) -- `docs/modeling/pink-mobile.mdx`: "Here's a code example of adding the Account#Owner role" above code that defines Plan#editor (reason: mislabeled; label changed to Plan#Editor, code unchanged) -- `docs/modeling/pink-mobile.mdx`: "Account#Editor: Can perform some editing operations on a User's account" (reason: contradicts setup.js, where account editor has only view; corrected) -- `docs/modeling/pink-mobile.mdx`: Owned Resources condition "resource.owner == user.id" (reason: setup.js uses ref user.key; corrected to user.key, set name to Owned Plans) -- `docs/modeling/pink-mobile.mdx`: "simple web application based on Node.js" (reason: repo README says Next.js; corrected) -- `docs/modeling/pink-mobile.mdx`: "filtering only the users who are owners of a plan" (reason: the owner role in setup.js is on Account; reworded to list owner role assignments) -- `docs/modeling/pink-mobile.mdx`: Slack link io.permit.io/blog-slack (reason: style guide requires io.permit.io/slack; replaced) -- `docs/modeling/rebac-GHC.mdx`: hosted demo https://ghc.up.railway.app/ with shared password Aa123456! for four accounts (reason: kept for owner review; site responded on 2026-09-17 with HTTP 307 to a Clerk sign-in page, credentials not tested; added a warning that accounts are public and shared; owner should decide whether to keep publishing shared passwords) -- `docs/modeling/rebac-GHC.mdx`: "In the Permit dashboard, go to Connect, and copy the token" (reason: volatile UI label; replaced with link to /overview/get-api-key) -- `docs/modeling/rebac-GHC.mdx`: ABAC date-range enforcement via custom Rego (reason: kept; not run end to end; custom.rego and root.rego verified to exist in permitio/Galactic-Health-Corporation and permitio/ghc-demo-policy) - -### Batch w21 (`how-to/manage-data` and related pages) - -- `docs/how-to/manage-data/loading-data.mdx`: "There are no practical limits on number of objects or object sizes." (reason: could not verify; removed) -- `docs/how-to/manage-data/loading-data.mdx`: "There are limits on the overall data volume that can be loaded to a single PDP, which can be bypassed via PDP Sharding" (reason: no stated limit found; restated as a pointer to Sharded Edge PDPs for very large data sets) -- `docs/how-to/manage-data/loading-data.mdx`: link to "OPAL-Data-(-EAP-)" API section as the reference for the default PDP data structure (reason: tag is Early Access and under /v2/internal/opal_data in openapi.json; removed) -- `docs/how-to/manage-data/loading-data.mdx`: "three ways" to load data (reason: page has four methods; corrected) -- `docs/how-to/manage-data/use-external-data-source.mdx`: "Custom scopes are supported from PDP v0.2.15" (reason: permitio/PDP tags start at 0.3.0, cannot verify; removed) -- `docs/how-to/manage-data/use-external-data-source.mdx`: "Scope Request (API still in beta)" (reason: dated wording, Scope-Configurations tag has no beta/EAP marker in openapi.json; removed) -- `docs/how-to/manage-data/use-external-data-source.mdx`: link to "OPAL-Data-(-EAP-)" API section (reason: EAP/internal endpoint; removed) -- `docs/how-to/manage-data/use-external-data-source.mdx`: OPAL_SPLIT_ROOT_DATA kept (verified: permitio/opal packages/opal-client/opal_client/config.py `SPLIT_ROOT_DATA`, OPAL_ prefix); custom_*_attributes merge order "input > custom > stored" kept (verified: permitio/generated-policy-example permit/utils/abac.rego) -- `docs/how-to/manage-data/use-external-data-source.mdx`: OPA data check at localhost:8181 now conditioned on exposing the OPA port (reason: PDP publishes OPA only when configured, per deploy-to-production#exposing-opa-within-the-pdp and `permit pdp run --opa`) -- `docs/how-to/manage-data/local-facts-uploader.mdx`: "Faster Sync Times: Despite increased request latency, data updates are typically received faster compared to data updates via the Permit API" (reason: could not verify; removed) -- `docs/how-to/manage-data/local-facts-uploader.mdx`: "CPU Usage: PDP CPU usage may increase with high traffic to proxy facts endpoints" (reason: could not verify; removed) -- `docs/how-to/manage-data/local-facts-uploader.mdx`: Supported APIs list omitted `DELETE /facts/users/{user_id}/roles` and `DELETE /facts/role_assignments` (reason: both wait for updates in PDP horizon/facts/router.py; added in prose). Versions 0.5.1 (wait timeout) and 0.8.0 (timeout policy, horizon/facts/timeout_policy.py added between 0.7.2 and 0.8.0) kept; note the wait-timeout dependency already exists in tag 0.5.0, so 0.5.1 is a safe but possibly conservative minimum. -- `docs/how-to/manage-data/local-facts-uploader.mdx`: "Uses PDP default if not specified" for SDK-level timeout (reason: true for Python/Node (default None/null), false for Go (`NewConfigBuilder` sets DefaultFactsSyncTimeout); prose narrowed to Python and Node.js; Go code comment logged in codefix) -- `docs/how-to/SDLC/modeling-implementation-components.mdx`: Data filtering "typically requires custom policy code to implement" (reason: contradicts /how-to/enforce-permissions/data-filtering, which offers bulkCheck, filterObjects, getUserPermissions, authorized_users, and partial evaluation; replaced) -- `docs/how-to/SDLC/modeling-implementation-components.mdx`: "While costly to create, this type of accessibility is vital..." and "our approach at Permit was to provide these capabilities out of the box" (reason: marketing asides; removed) -- `docs/how-to/SDLC/modeling-implementation-components.mdx`: "Generally, each account should have one workspace" (reason: softened to "Most companies need one workspace", consistent with quickstart) -- `docs/how-to/SDLC/modeling-implementation-components.mdx`: "Data Plane" for users/tenants data (reason: conflicts with glossary data plane = PDPs; kept the diagram's name and added a disambiguation note linking to how-does-it-work#permits-hybrid-architecture) -- `docs/how-to/SDLC/authz-testing.mdx`: "In Permit, we incorporate these tests into our development cycles, allowing for thorough validation" (reason: vague, unverifiable; removed) -- `docs/how-to/SDLC/CI-CD.mdx`: "which minimizes the risk of errors and maximizes operational efficiency" / "enhances security by reducing the risk of misconfigurations" (reason: unsupported generalizations; removed) -- `docs/api/examples/filter-role-associations.mdx`: "If multiple tenants are received, the last tenant will be compared with the resource instance." (reason: restated precisely from the openapi.json `tenant` parameter description, including the 404 failure mode) -- `docs/api/examples/filter-role-associations.mdx`: role_assignments filter values "key or ID" not stated (reason: spec does not say IDs are accepted for user/tenant/role; table says key) -- `docs/api/examples/filter-users.mdx`: "You can use `role_id` or `role_key` to filter users by role" (reason: spec says only "Match users with a specific role"; restated as role key) -- `docs/api/examples/list-user-permissions.mdx`: "Remove duplicates and get the final list of permitted roles" (reason: meant permissions; also the method ignores resource-instance roles, ReBAC derivations, and ABAC; added pointer to getUserPermissions() and the `extends` inheritance from RoleRead schema) -- `docs/quickstart.mdx`: sign-in options "Google or GitHub" (reason: sign-in screenshot on the page also shows Microsoft; added Microsoft) -- `docs/quickstart.mdx`: Slack link `io.permit.io/docs-to-slack` (reason: style guide Slack URL is io.permit.io/slack; changed) -- `docs/quickstart.mdx`: new text click paths (Policy > Roles / Resources / Policy Editor tabs, Directory > Add user > Top Level Access) and workspace fields (Workspace Name, Workspace Key, Launch Your Account) taken from building-rbac-policy.mdx and the onboarding screenshot; "Permit fills in a URL-friendly key from the name" is inferred from the screenshot (Company A -> company-a), not from source. - -## Per-page scores - -| Page | Audience | Type | Aud | Task | Type | Acc | Str | Ex | Term | AI | Mnt | Sty | Total | Before | Top issues | -|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| -| `docs/ai-security/access-request-mcp/food-ordering-demo-example.mdx` | AI agent builder | tutorial | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 5 | three code blocks run 28 to 33 lines; the uv add list omits rich>=13.9.4 and the import path differs from the upstream repo layout | -| `docs/ai-security/access-request-mcp/implementation-guide.mdx` | implementer | mixed | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | **17** | 7 | move Tool reference and Best practices to their own pages or clearly separate them from the how-to; replace the `...` list_dishes stub and undefined `firstname` in sync_user with runnable snippets; remove the duplicated sync_user snippet | -| `docs/ai-security/access-request-mcp/overview.mdx` | decision maker | explanation | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 10 | 'Permit stores the request in a User Management element' is imprecise (the element config scopes the request); add a sequence diagram of the access request and operation approval flows | -| `docs/ai-security/framework.mdx` | decision maker | explanation | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 10 | explanation page with diagrams and guide links, no runnable example of its own | -| `docs/ai-security/integrations/langchain.mdx` | AI agent builder | tutorial | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 8 | code blocks run 26 to 41 lines | -| `docs/ai-security/integrations/langflow.mdx` | AI agent builder | tutorial | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | 1 | 2 | **17** | 5 | permissions_check.py never wires validate_auth() into its outputs so every flow denies, and data_protection.py raises AttributeError: both are documented but the fix belongs in permit-langflow-framework; the tutorial also needs an Astra DB flights collection whose schema and seed data the page never gives, and three of the components it uses are Langflow legacy | -| `docs/ai-security/integrations/mongodb-rag.mdx` | AI agent builder | tutorial | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | **20** | 7 | delete the duplicated index JSON, env block, and clone/docker-compose steps in 'Run the pipeline step by step' (which conflicts with the Docker quickstart); manual dashboard model uses alice/bob and omits department view/member grant, align with user_engineering_1 etc.; add a sample JSON response for the curl | -| `docs/ai-security/integrations/openai-prompt-filtering.mdx` | AI agent builder | tutorial | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 6 | the page presents its own improved classifier as the example repo's: the repo hardcodes gpt-4 and has no OPENAI_MODEL or response_format; two blocks run 32 to 38 lines | -| `docs/ai-security/integrations/pydantic-ai.mdx` | AI agent builder | tutorial | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 6 | three code blocks run 33 to 37 lines | -| `docs/api/api-reference.mdx` | implementer | reference | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | **18** | 13 | add one minimal curl call with expected response; iframe embed with inline styles is fragile | -| `docs/api/api-with-cli.mdx` | implementer | mixed | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | **19** | 10 | several behavior claims have no public source: the 403 scope semantics, 'the request has no effect' on a 429, the backoff prescription, the API log's scope, and page_count | -| `docs/api/background-tasks.mdx` | implementer | reference | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | **19** | 11 | HTTP 200 on failed task and wait=0 default are not stated in the OpenAPI spec; confirm or mark | -| `docs/api/elements/access-request-api.mdx` | implementer | reference | 2 | 1 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 7 | no example request for the API-key variant: add one curl (create + approve) with Authorization header and response | -| `docs/api/elements/access-requests.mdx` | implementer | reference | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | **18** | 6 | login setup section duplicated verbatim on the Operation Approval API page: move to a shared partial; identical 20-line response JSON repeated 6 times, show only changed fields | -| `docs/api/elements/operation_approval.mdx` | implementer | reference | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | **18** | 6 | duplicated login section (shared partial); origin header present on access request curls but absent here, make consistent | -| `docs/api/elements/overview.mdx` | implementer | landing | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 2 | 2 | 2 | **18** | 8 | add sample response JSON; placeholder style and origin app.permit.io differ from sibling pages | -| `docs/api/examples/autopopulate-actions.mdx` | implementer | how-to | 2 | 2 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | **17** | 12 | settings.default_resource_actions is not in the OpenAPI schema, cite source; add response excerpt; placeholder permit_env_api_key differs from API_SECRET_KEY used on sibling pages | -| `docs/api/examples/create-tenant.mdx` | implementer | how-to | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | **19** | 12 | sample objects carry 2023 timestamps and xxxx IDs (minor) | -| `docs/api/examples/filter-relationship-tuple.mdx` | implementer | reference | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | **19** | 12 | include_total_count response shape not mentioned (API returns array or paginated object) | -| `docs/api/examples/filter-role-associations.mdx` | implementer | reference | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | **19** | 12 | 'role association' synonym and {project}/{project_id} placeholder variants; closing claim that role attributes 'separate the roles that belong to each tenant' is vague | -| `docs/api/examples/filter-users.mdx` | implementer | reference | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 2 | 1 | 2 | **17** | 12 | commented-out curl inside the role example: split into two blocks; same user JSON repeated 4 times; tenant_id placeholder unbraced vs {project_id}; search_operator not documented | -| `docs/api/examples/get-project-and-env.mdx` | implementer | how-to | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | **19** | 12 | unverified that an environment API key can list all projects; state the key scope needed | -| `docs/api/examples/list-user-permissions.mdx` | implementer | how-to | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | **18** | 11 | combine step has no code: add a short script that merges permissions incl. extends; user JSON repeated three times | -| `docs/api/pdp-api-reference.mdx` | implementer | reference | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 12 | add one example PDP call (e.g. POST /allowed) with response | -| `docs/api/pdp-statistics.mdx` | operator | reference | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | **19** | 11 | sample responses pin 2024 dates and pdp 0.2.37; title Title Case not task; state table lists 'main values' only (spec has 8) | -| `docs/api/pdp-webhooks.mdx` | operator | how-to | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 10 | webhooks endpoint absent from public OpenAPI and 'several retries' is vague: state retry count/timing; add run command and a local test for the receiver | -| `docs/api/rbac/disable-rebac-to-increase-performance.mdx` | operator | how-to | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | **19** | 12 | rebac_disabled is not in the OpenAPI schema and the performance benefit is unquantified; cite source | -| `docs/api/rbac/rbac-example.mdx` | implementer | tutorial | 2 | 2 | 2 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | **18** | 4 | 35-line block of five curls: split per step; no response samples; use example.com emails; verify step should show the check call | -| `docs/api/rebac/groups/groups-ui.mdx` | implementer | how-to | 1 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 1 | 2 | **17** | 9 | audience 'developers and administrators' is mixed; 'child group must share the parent resource type' unverified; seven UI screenshots will rot | -| `docs/api/rebac/groups/groups.mdx` | implementer | mixed | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | **19** | 5 | endpoint reference table, two walkthroughs and list/get operations share one page; four endpoints marked early access | -| `docs/api/rebac/rebac-api-calls.mdx` | implementer | reference | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | **18** | 11 | SDK tabs inconsistent (Python only for relations, Node only elsewhere); curl shell variables never shown being set; derivation example leans on 'the relationship tuple from the previous section' | -| `docs/api/v2-migration-guide.mdx` | maintainer | mixed | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | **18** | 8 | the verify step compares a check through a v2 and a v1 PDP without saying that needs two SDK versions; procedure and reference share one page | -| `docs/api/working-with-abac/building-conditions.mdx` | implementer | reference | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 7 | the example now headed 'Valid: two conditions on the same attribute' is byte-identical to one the published page labels INVALID, and the anchor is still {#invalid-1}: needs a live condition_sets call to settle; the 422 validation claims are not in the OpenAPI spec; the examples are condition fragments rather than runnable calls | -| `docs/api/working-with-abac/condition-set-rules.mdx` | implementer | reference | 2 | 1 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 6 | show a complete curl for POST/GET/DELETE set_rules and say where proj_id/env_id come from; show the actual JSON response of the create and verify calls; tag JSON bodies as json not javascript | -| `docs/api/working-with-abac/condition-sets.mdx` | implementer | mixed | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **16** | 7 | add a full curl request and sample response for create and verify; example user set tests user.role as an attribute and resource set re-tests resource.type despite resource_id (explain or remove); move the permission matrix to the rules page so this stays a how-to | -| `docs/api/working-with-abac/examples.mdx` | implementer | how-to | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | **20** | 6 | uses 'user.role equals student' and models '5 PM' as a static resource attribute, both questionable for real ABAC; JSON bodies tagged javascript with no curl/headers; key says stanford while text never defines it, 'the same endpoint' needs prior context | -| `docs/api/working-with-abac/operators.mdx` | implementer | reference | 2 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | 2 | **18** | 9 | operand-type column is inconsistent ('Array attribute' for array_contains; ref table lists Array for equals); ref comparison rows 'a < user.age' leave 'a' undefined; state which PDP types evaluate object_match/fk_resource_type (ABAC is Edge PDP only) | -| `docs/api/working-with-abac/overview.mdx` | implementer | landing | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **16** | 3 | says an ABAC policy is 'three objects' then tables four; build steps give endpoints but no request bodies; mixes prereqs, concepts, steps, endpoint reference and reading order | -| `docs/authentication/auth0/auth0-demo-app.mdx` | implementer | mixed | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 8 | one 44-line tsx block | -| `docs/authentication/auth0/auth0-sync-script.mdx` | implementer | how-to | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | **18** | 11 | step 2 says open the auth0 folder then step 3 runs cd admin-scripts/auth0 (pick one); untagged code block for the location response and mixed [bracket] placeholder styles; Auth0 dashboard click paths are volatile, link Auth0 docs | -| `docs/authentication/auth0/permit-integration.mdx` | implementer | mixed | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 1 | **16** | 6 | snippets use deprecated top-level permit.api.assignRole/getUser, and getUser throws for a new user so the early-return sample fails on first login (use permit.api.users.get with try/catch); step 3 short snippet and step 5 use permit/auth0User without showing where they come from; long code duplicated from the demo page and comments say 'we will use it' | -| `docs/authentication/cognito/cognito-demo-app.mdx` | implementer | mixed | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | **19** | 8 | the page has the reader patch upstream code inline, which goes stale if permitio/cognito-integration is fixed; 'hosted login page' no longer matches the AWS console, which now says managed login | -| `docs/authentication/cognito/permit-integration.mdx` | implementer | how-to | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 1 | **17** | 9 | intro says examples come from the demo app but the sync route here differs (id_token, fixed payload scope), so say it is a corrected version; split the 60-line backend block and add the express app setup; remove casual code comments ('After we got the tokens') | -| `docs/authentication/fusionauth.mdx` | implementer | landing | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 2 | **16** | 4 | no code at all: add the current-SDK handoff snippet (syncUser, assignRole, check) instead of only prose; example repo lives in a personal account (filipermit) on permitio 0.0.5, state support status; add a verify step for running the example | -| `docs/authentication/hankopermit.mdx` | implementer | tutorial | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 2 | **16** | 6 | ABAC section needs a container PDP but gives no run command or URL to set; code blocks lack language and have broken indentation/ellipses; 14 dashboard screenshots | -| `docs/authentication/logto.mdx` | implementer | tutorial | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 1 | **16** | 11 | npx create-next-app now defaults to App Router but the tutorial requires Pages Router (add the flag); libraries/permit.js mixes require() with export, and the check-permission block has no language tag; split 100+ line page components and retitle to the task | -| `docs/authentication/permit-and-authentication.mdx` | decision maker | explanation | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 8 | no handoff-point code snippet (sync + check) to anchor the concept; title in Title Case | -| `docs/authentication/stytch/permit-integration.mdx` | implementer | tutorial | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | **19** | 6 | styles is a deprecated StytchLogin prop; three blocks run 33 to 46 lines | -| `docs/authentication/supertokens.mdx` | implementer | how-to | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | **20** | 4 | example lives in a personal repo (filipermit) on permitio 0.0.5, so running it likely needs fixes; code blocks lack language tags; webinar + screenshot gallery sections dilute the tutorial | -| `docs/authentication/your-authentication.mdx` | implementer | explanation | 2 | 1 | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | **16** | 8 | add a code sample for the handoff point (verify JWT, syncUser, assignRole, check) instead of only links; provider table plus generic how-to mixes landing and how-to; video and third-party provider list need a review marker | -| `docs/concepts/control-plane-and-data-plane.mdx` | new user | explanation | 2 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | 2 | **18** | 14 | data plane section omits Nexus PDP and the Cloud PDP case where Permit runs the data plane; heading 'Local PDP' vs 'Edge PDP' naming used elsewhere | -| `docs/concepts/deployment-options.mdx` | decision maker | explanation | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | **18** | 14 | light on-premise row is vague about what stays in your network vs Permit's cloud; no mention of Cloud PDP or Nexus PDP as options; the get-started path is only 'email support' | -| `docs/concepts/differentiator-checklist.mdx` | decision maker | explanation | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | **20** | 13 | none | -| `docs/concepts/multi-tenant-authorization.mdx` | implementer | explanation | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 1 | **17** | 10 | benefit 'Load balancing and scaling' is not provided by tenant authorization, remove; add an assignRole-in-tenant example and show the deny for a cross-tenant check; 'first-class object'/'silo' phrasing | -| `docs/concepts/oss-fallback.mdx` | decision maker | explanation | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 1 | **16** | 9 | migration steps are high level with no pointer to the exported policy layout or an OPAL server config example; 'Permit is not an open-core company' and 'The choice to stay or leave stays with you' are filler; note that Nexus PDP (pdp-v3) is not in the open-source list | -| `docs/concepts/pdp/cloud-pdp-benchmarks.mdx` | operator | reference | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 1 | 2 | **18** | 14 | October 2025 run with no load tool, client location, or data set size described, so results are not reproducible; mark when figures will be refreshed | -| `docs/concepts/pdp/cloud-pdp-capabilities.mdx` | implementer | reference | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 2 | **17** | 11 | 'Cloud PDP and Edge PDP evaluate the same policy model' contradicts the ABAC-not-supported table above it; rate-limit numbers need a 'subject to change' marker; Debug Mode for Cloud PDP needs the exact API call | -| `docs/concepts/pdp/configuration.mdx` | operator | reference | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 2 | 1 | 2 | **17** | 12 | PDP_OPA_BEARER_TOKEN_REQUIRED refers to undefined CLIENT_TOKEN; add a Kubernetes env example alongside the docker link; define 'PDP server' vs 'Horizon' vs Edge PDP once at the top | -| `docs/embeddable-uis/element-login.mdx` | implementer | how-to | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 | **18** | 7 | element_bearer_token is a real API field but is not declared in permitio 2.7.6's response types, so the private-browsing sample does not type-check in TypeScript; four blocks run 35 to 42 lines | -| `docs/embeddable-uis/element/access-request.mdx` | implementer | how-to | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 2 | **17** | 8 | iframe sample uses self-closing ; 'Level 1 (Workspace Owner) reviews requests' is unsourced, link the exact setting; 9 dashboard screenshots plus video, drop the redundant User Management form screenshots from Prerequisites | -| `docs/embeddable-uis/element/approval-management.mdx` | implementer | how-to | 2 | 2 | 2 | 1 | 2 | 1 | 2 | 2 | 1 | 2 | **17** | 8 | self-closing