From 2487f8db093c59a7f81872b3604e30c690767db8 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 11:34:07 -0400 Subject: [PATCH 01/17] docs(authzed): product-availability pill on concept pages; frame Audit Logging's self-hosted section as SpiceDB Enterprise A reader from Zoom landed on audit-logging#self-hosted and read it as SpiceDB open source. The only scope sentence was line 10 of the page, and 'Self-Hosted' collides with self-hosting OSS. - ProductBadge: 'Available on' + every tier in Feature Matrix order; unavailable tiers stay in the row, struck out; DIY tiers mirror the matrix's DIY cells - Audit Logging: pill under the H1, section renamed 'SpiceDB Enterprise (self-hosted)' keeping the #self-hosted anchor, Enterprise-only callout above the flag table - Same pill on Restricted API Access, Workload Isolation, Private Networking, Management Dashboard --- app/authzed/concepts/audit-logging/page.mdx | 12 ++- .../concepts/management-dashboard/page.mdx | 2 + .../concepts/private-networking/page.mdx | 4 +- .../concepts/restricted-api-access/page.mdx | 4 +- .../concepts/workload-isolation/page.mdx | 4 +- components/product-badge.css | 81 +++++++++++++++++++ components/product-badge.tsx | 69 ++++++++++++++++ lib/products.ts | 35 ++++++++ mdx-components.ts | 2 + 9 files changed, 208 insertions(+), 5 deletions(-) create mode 100644 components/product-badge.css create mode 100644 components/product-badge.tsx create mode 100644 lib/products.ts diff --git a/app/authzed/concepts/audit-logging/page.mdx b/app/authzed/concepts/audit-logging/page.mdx index 2ad53d6f..c7d2bed7 100644 --- a/app/authzed/concepts/audit-logging/page.mdx +++ b/app/authzed/concepts/audit-logging/page.mdx @@ -7,7 +7,10 @@ import { Callout, Tabs } from "nextra/components"; # Audit Logging -Audit Logging is functionality exclusive to AuthZed products that publishes logs of SpiceDB API operations to a log sink. + + +Audit Logging publishes logs of SpiceDB API operations to a log sink. +It ships with AuthZed Cloud, Dedicated, and Enterprise; SpiceDB open source does not include it. ## Log Format @@ -171,7 +174,12 @@ The process for setting up audit logging varies depending on the AuthZed product Using the web dashboard, navigate to the Permission System's settings page to find the Audit Log settings. -### Self-Hosted +### SpiceDB Enterprise (self-hosted) [#self-hosted] + + + **AuthZed Enterprise only.** The `--extender-audit-*` flags below exist in the AuthZed-licensed SpiceDB Enterprise binary. + They are not present in [SpiceDB open source](/authzed/guides/picking-a-product#open-source), which has no audit logging. + Use the following command-line flags: diff --git a/app/authzed/concepts/management-dashboard/page.mdx b/app/authzed/concepts/management-dashboard/page.mdx index 03b3c265..ba136ffb 100644 --- a/app/authzed/concepts/management-dashboard/page.mdx +++ b/app/authzed/concepts/management-dashboard/page.mdx @@ -5,6 +5,8 @@ description: "A web-based application for platform operators to configure and mo # Management Dashboard + + The Management Dashboard is a web-based application for organizations to manage SpiceDB deployments. The dashboard is primarily targeting platform operators that want to configure and monitor the service. diff --git a/app/authzed/concepts/private-networking/page.mdx b/app/authzed/concepts/private-networking/page.mdx index dc8e7d69..f1ada3d4 100644 --- a/app/authzed/concepts/private-networking/page.mdx +++ b/app/authzed/concepts/private-networking/page.mdx @@ -7,7 +7,9 @@ import { Callout } from "nextra/components"; # Private Networking -Private Networking is functionality exclusive to AuthZed Dedicated that restricts network access to internal networks. + + +Private Networking restricts network access to internal networks. When enabled, connections that are not configured are rejected. By adding this additional layer of security, entire classes of security risk are eliminated because only trusted networks have access to the software powering your authorization systems. diff --git a/app/authzed/concepts/restricted-api-access/page.mdx b/app/authzed/concepts/restricted-api-access/page.mdx index 150b0037..dabbcc5c 100644 --- a/app/authzed/concepts/restricted-api-access/page.mdx +++ b/app/authzed/concepts/restricted-api-access/page.mdx @@ -7,7 +7,9 @@ import { Callout, Tabs } from "nextra/components"; # Restricted API Access -Restricted API Access is functionality exclusive to AuthZed products that restricts access to SpiceDB for API Tokens. + + +Restricted API Access restricts access to SpiceDB for API Tokens. This functionality enables organizations to apply the principle of least-privilege to services accessing SpiceDB. For example, read-only tokens can be created for services that should never need to write to SpiceDB. diff --git a/app/authzed/concepts/workload-isolation/page.mdx b/app/authzed/concepts/workload-isolation/page.mdx index 718846a9..c0eea19a 100644 --- a/app/authzed/concepts/workload-isolation/page.mdx +++ b/app/authzed/concepts/workload-isolation/page.mdx @@ -7,7 +7,9 @@ import YouTube from "@/components/youtube-wrapper"; # Workload Isolation -Workload Isolation is functionality exclusive to AuthZed products by which we give your SpiceDB deployments access to hardware that is only used by you, to guarantee performance and prevent "noisy neighbor" problems. + + +Workload Isolation gives your SpiceDB deployments access to hardware that is only used by you, to guarantee performance and prevent "noisy neighbor" problems. ## Control Plane diff --git a/components/product-badge.css b/components/product-badge.css new file mode 100644 index 00000000..e9adc3ce --- /dev/null +++ b/components/product-badge.css @@ -0,0 +1,81 @@ +/* Product-availability pills — which AuthZed tiers a feature ships on. + Geometry and type match feature-badge.css so the two pill families read as + one system when they sit under adjacent H1s. Colour is deliberately a + single brand accent (--sand-300, the same token the site uses for links) + rather than one hue per product: the pills answer "is it on the tier I + use?", and a struck, dimmed pill answers "no" faster than a colour key. */ + +.product-badge-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + margin: 1.5rem 0 1.75rem; +} + +.product-badge-label { + margin-right: 0.25rem; + font-family: var(--font-mono, ui-monospace, monospace); + font-size: 0.7rem; + font-weight: 500; + letter-spacing: 0.12em; + text-transform: uppercase; + color: hsl(var(--stone-500, 30 5% 50%)); + text-decoration: none; +} + +.product-badge-label:hover { + text-decoration: underline; +} + +.product-badge { + display: inline-flex; + align-items: baseline; + gap: 0.4em; + padding: 0.25rem 0.75rem; + border: 1px solid; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 500; + text-decoration: none; +} + +.product-badge-yes { + color: hsl(var(--sand-300)); + background: hsl(var(--sand-300) / 0.1); + border-color: hsl(var(--sand-300) / 0.5); +} + +/* Present but unavailable: kept in the row so absence is legible. */ +.product-badge-no { + color: hsl(var(--stone-500, 30 5% 50%) / 0.7); + background: transparent; + border-color: hsl(var(--stone-500, 30 5% 50%) / 0.25); +} + +.product-badge-no s { + text-decoration-thickness: 1px; +} + +.product-badge-diy { + color: hsl(var(--stone-500, 30 5% 50%)); + background: transparent; + border-color: hsl(var(--stone-500, 30 5% 50%) / 0.4); +} + +.product-badge-suffix { + font-family: var(--font-mono, ui-monospace, monospace); + font-size: 0.6rem; + letter-spacing: 0.1em; + opacity: 0.8; +} + +.product-badge-sr { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; +} diff --git a/components/product-badge.tsx b/components/product-badge.tsx new file mode 100644 index 00000000..b62b3e26 --- /dev/null +++ b/components/product-badge.tsx @@ -0,0 +1,69 @@ +import "./product-badge.css"; +import Link from "next/link"; +import { + FEATURE_MATRIX_HREF, + PRODUCTS, + PRODUCT_ORDER, + type ProductKey, +} from "@/lib/products"; + +/* Which AuthZed products a page's feature ships on. Used in MDX right under + the H1 of a concept page: + + + + + Every tier is always rendered, in Feature Matrix order, so the reader sees + what a feature is NOT on as clearly as what it is on. A prose sentence + ("exclusive to AuthZed products") blends into the intro; a struck-out + "Open Source" pill does not. `diy` mirrors the matrix's DIY cells: you can + build it yourself, we don't ship it. + + Sibling of feature-badge.tsx (Materialize feature identity). This one is + props-driven rather than route-driven because availability is per-page + data the author states, not something derivable from the URL. */ +type Props = { + available: readonly ProductKey[]; + diy?: readonly ProductKey[]; +}; + +export function ProductBadge({ available, diy = [] }: Props) { + return ( + + + Available on + + {PRODUCT_ORDER.map((key) => { + const { label, href } = PRODUCTS[key]; + const state = available.includes(key) + ? "yes" + : diy.includes(key) + ? "diy" + : "no"; + return ( + + {state === "no" ? {label} : label} + {state === "diy" && ( + DIY + )} + + {state === "yes" + ? " (available)" + : state === "diy" + ? " (build it yourself)" + : " (not available)"} + + + ); + })} + + ); +} diff --git a/lib/products.ts b/lib/products.ts new file mode 100644 index 00000000..bff86edd --- /dev/null +++ b/lib/products.ts @@ -0,0 +1,35 @@ +/* The AuthZed product tiers, in the order the Feature Matrix on + authzed/guides/picking-a-product lists them. Single source for the + product-availability pill (components/product-badge.tsx) so page markers + and the matrix name the same tiers with the same links. */ + +export const PRODUCTS = { + "open-source": { + label: "Open Source", + href: "/authzed/guides/picking-a-product#open-source", + }, + cloud: { + label: "Cloud", + href: "/authzed/guides/picking-a-product#cloud", + }, + dedicated: { + label: "Dedicated", + href: "/authzed/guides/picking-a-product#dedicated", + }, + enterprise: { + label: "Enterprise", + href: "/authzed/guides/picking-a-product#enterprise", + }, +} as const; + +export type ProductKey = keyof typeof PRODUCTS; + +export const PRODUCT_ORDER: readonly ProductKey[] = [ + "open-source", + "cloud", + "dedicated", + "enterprise", +]; + +export const FEATURE_MATRIX_HREF = + "/authzed/guides/picking-a-product#feature-matrix"; diff --git a/mdx-components.ts b/mdx-components.ts index 699f653a..f7f7f9d8 100644 --- a/mdx-components.ts +++ b/mdx-components.ts @@ -2,6 +2,7 @@ import { useMDXComponents as getDocsMDXComponents } from "nextra-theme-docs"; import type { Component } from "react"; import { Yes, No } from "@/components/feature-icon"; import { FeatureBadge } from "@/components/feature-badge"; +import { ProductBadge } from "@/components/product-badge"; const docsComponents = getDocsMDXComponents(); @@ -10,5 +11,6 @@ export const useMDXComponents = (components?: Component) => ({ Yes, No, FeatureBadge, + ProductBadge, ...components, }); From c01545d590ceeca80bcb484690c7743a211ee3b1 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:09:07 -0400 Subject: [PATCH 02/17] docs(authzed): ProductBadge final form after design lab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spelled-out 'Not in …' pill replaces struck-out tiers (three rounds with Corey: strikethrough reads slow, product colour-coding adds a decode step). DIY tiers are dashed stone with a mono DIY suffix; nothing excluded means no negative pill. Lab route and variants removed. --- components/product-badge.css | 43 ++++++++---------- components/product-badge.tsx | 88 +++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 64 deletions(-) diff --git a/components/product-badge.css b/components/product-badge.css index e9adc3ce..4d2b42de 100644 --- a/components/product-badge.css +++ b/components/product-badge.css @@ -1,9 +1,9 @@ /* Product-availability pills — which AuthZed tiers a feature ships on. Geometry and type match feature-badge.css so the two pill families read as - one system when they sit under adjacent H1s. Colour is deliberately a - single brand accent (--sand-300, the same token the site uses for links) - rather than one hue per product: the pills answer "is it on the tier I - use?", and a struck, dimmed pill answers "no" faster than a colour key. */ + one system when they sit under adjacent H1s. Three states, three treatments: + sand = ships with it, dashed stone = you can build it yourself (the Feature + Matrix's DIY), solid stone = not available. The negative is a spelled-out "Not in …" pill, + never a struck or dimmed tier: absence has to read in one glance. */ .product-badge-row { display: flex; @@ -20,12 +20,7 @@ font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; - color: hsl(var(--stone-500, 30 5% 50%)); - text-decoration: none; -} - -.product-badge-label:hover { - text-decoration: underline; + color: hsl(30 5% 50%); } .product-badge { @@ -40,34 +35,36 @@ text-decoration: none; } +/* --sand-300 flips itself under html.dark (app/globals.css). */ .product-badge-yes { color: hsl(var(--sand-300)); background: hsl(var(--sand-300) / 0.1); border-color: hsl(var(--sand-300) / 0.5); } -/* Present but unavailable: kept in the row so absence is legible. */ -.product-badge-no { - color: hsl(var(--stone-500, 30 5% 50%) / 0.7); +.product-badge-diy { + color: inherit; background: transparent; - border-color: hsl(var(--stone-500, 30 5% 50%) / 0.25); + border-color: hsl(30 5% 50% / 0.6); + border-style: dashed; } -.product-badge-no s { - text-decoration-thickness: 1px; -} - -.product-badge-diy { - color: hsl(var(--stone-500, 30 5% 50%)); - background: transparent; - border-color: hsl(var(--stone-500, 30 5% 50%) / 0.4); +.product-badge-not { + color: inherit; + background: hsl(30 5% 50% / 0.12); + border-color: hsl(30 5% 50% / 0.45); } .product-badge-suffix { font-family: var(--font-mono, ui-monospace, monospace); font-size: 0.6rem; letter-spacing: 0.1em; - opacity: 0.8; + opacity: 0.85; +} + +.product-badge-glyph { + font-size: 0.7rem; + line-height: 1; } .product-badge-sr { diff --git a/components/product-badge.tsx b/components/product-badge.tsx index b62b3e26..fa390868 100644 --- a/components/product-badge.tsx +++ b/components/product-badge.tsx @@ -1,11 +1,6 @@ import "./product-badge.css"; import Link from "next/link"; -import { - FEATURE_MATRIX_HREF, - PRODUCTS, - PRODUCT_ORDER, - type ProductKey, -} from "@/lib/products"; +import { PRODUCTS, PRODUCT_ORDER, type ProductKey } from "@/lib/products"; /* Which AuthZed products a page's feature ships on. Used in MDX right under the H1 of a concept page: @@ -13,11 +8,13 @@ import { - Every tier is always rendered, in Feature Matrix order, so the reader sees - what a feature is NOT on as clearly as what it is on. A prose sentence - ("exclusive to AuthZed products") blends into the intro; a struck-out - "Open Source" pill does not. `diy` mirrors the matrix's DIY cells: you can - build it yourself, we don't ship it. + Reads left to right as a sentence: AVAILABLE ON, the tiers that have it + (sand), the tiers where you build it yourself (dashed, DIY suffix; mirrors + the Feature Matrix's DIY cells), then one stone "Not in …" pill naming the + tiers that don't. The negative is spelled out rather than shown by + striking or dimming a pill: a reader who lands mid-page from a deep link + needs "not in Open Source" in one glance, not a decode. A page where + nothing is excluded gets no negative pill at all. Sibling of feature-badge.tsx (Materialize feature identity). This one is props-driven rather than route-driven because availability is per-page @@ -28,42 +25,51 @@ type Props = { }; export function ProductBadge({ available, diy = [] }: Props) { + const yes = PRODUCT_ORDER.filter((k) => available.includes(k)); + const build = PRODUCT_ORDER.filter( + (k) => !available.includes(k) && diy.includes(k), + ); + const missing = PRODUCT_ORDER.filter( + (k) => !available.includes(k) && !diy.includes(k), + ); + return ( - - Available on - - {PRODUCT_ORDER.map((key) => { - const { label, href } = PRODUCTS[key]; - const state = available.includes(key) - ? "yes" - : diy.includes(key) - ? "diy" - : "no"; - return ( - - {state === "no" ? {label} : label} - {state === "diy" && ( - DIY - )} - - {state === "yes" - ? " (available)" - : state === "diy" - ? " (build it yourself)" - : " (not available)"} - - - ); - })} + Available on + {yes.map((k) => ( + + {PRODUCTS[k].label} + + ))} + {build.map((k) => ( + + {PRODUCTS[k].label} + + (build it yourself) + + ))} + {missing.length > 0 && ( + + + Not in {missing.map((k) => PRODUCTS[k].label).join(", ")} + + )} ); } From 72161af85fa99a8cfbf8df11552fff09e23a31c9 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:39:04 -0400 Subject: [PATCH 03/17] docs: restyle markdown tables site-wide Nextra's default is a full grid (1px on every cell, zebra rows, 16px body, px-4 py-2). On flag lists and feature matrices it reads as a spreadsheet. Now: horizontal rules only, a mono uppercase header row, 14px body, tighter cells, row hover. Long code values (connection URIs) break instead of pushing the table into a horizontal scroll; the last column keeps a 6rem floor so short values like 1000000 stay on one line. 18 pages carry tables; four checked in both themes. --- app/globals.css | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/app/globals.css b/app/globals.css index a130fd32..43623b44 100644 --- a/app/globals.css +++ b/app/globals.css @@ -289,3 +289,118 @@ html.dark-mode { display: inline-flex; } } + +/* ── Tables ───────────────────────────────────────────────────────────────── + Nextra's default MDX table is a full grid: 1px borders on every cell, zebra + rows, 16px body text, generous padding. On reference tables (flag lists, + feature matrices) that reads as a spreadsheet and fights the page. This + restyles every markdown table to horizontal rules only, a quiet mono + header row, and slightly smaller type, in the same register as the + Feature Matrix and the web comparison tables. Unlayered so it wins over + Nextra's `x:` utilities without !important. */ + +.nextra-content table, +article table { + --tbl-rule: hsl(280 5% 84%); + --tbl-head-rule: hsl(280 6% 60%); + --tbl-hover: hsl(300 8% 96%); + --tbl-head: hsl(280 4% 44%); + font-size: 0.875rem; + line-height: 1.5; + border-collapse: collapse; +} +html.dark .nextra-content table, +html.dark article table { + --tbl-rule: hsl(279 9% 22%); + --tbl-head-rule: hsl(279 8% 40%); + --tbl-hover: hsl(279 12% 11%); + --tbl-head: hsl(280 4% 58%); +} + +.nextra-content table tr, +article table tr { + border: 0; + border-bottom: 1px solid var(--tbl-rule); + background: transparent; +} +.nextra-content table thead tr, +article table thead tr { + border-bottom: 1px solid var(--tbl-head-rule); +} +.nextra-content table tbody tr:last-child, +article table tbody tr:last-child { + border-bottom: 1px solid var(--tbl-head-rule); +} +.nextra-content table tbody tr:hover, +article table tbody tr:hover { + background: var(--tbl-hover); +} + +.nextra-content table th, +.nextra-content table td, +article table th, +article table td { + border: 0; + padding: 0.55rem 0.75rem; + vertical-align: top; + text-align: left; +} +.nextra-content table th:first-child, +.nextra-content table td:first-child, +article table th:first-child, +article table td:first-child { + padding-left: 0.25rem; +} +.nextra-content table th:last-child, +.nextra-content table td:last-child, +article table th:last-child, +article table td:last-child { + padding-right: 0.25rem; +} + +/* Header row: mono, small, tracked, muted. A label, not a bold sentence. */ +.nextra-content table th, +article table th { + padding-top: 0.25rem; + padding-bottom: 0.5rem; + font-family: var(--font-mono, ui-monospace, monospace); + font-size: 0.7rem; + font-weight: 500; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--tbl-head); +} + +/* Centered columns (Feature Matrix) keep their alignment from the markdown. */ +.nextra-content table th[style*="text-align: center"], +.nextra-content table td[style*="text-align: center"], +article table th[style*="text-align: center"], +article table td[style*="text-align: center"] { + text-align: center; +} + +/* First column is the row's identifier: keep it from collapsing, break it only + at a hyphen or space. Long code values (connection URIs) may break anywhere + rather than push the table sideways. */ +.nextra-content table td:first-child, +article table td:first-child { + min-width: 11rem; + overflow-wrap: normal; +} +.nextra-content table td code, +.nextra-content table td code.nextra-code, +article table td code, +article table td code.nextra-code { + font-size: 0.8em; + white-space: normal; + /* word-break, not overflow-wrap: Nextra's own `code.nextra-code` rule pins + overflow-wrap to break-word, which does not shrink a cell's min-content, + so a long URI would still push the table sideways. */ + word-break: break-word; +} +/* Trailing column is usually a short value (default, type). A floor keeps + `1000000` on one line while a long URI in the same slot still wraps. */ +.nextra-content table td:last-child, +article table td:last-child { + min-width: 6rem; +} From 5581532c6b793d0bf0f79fce4e8c94a8639b63e0 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:47:16 -0400 Subject: [PATCH 04/17] docs(authzed): backtick the flag names in the Audit Logging and Restricted API Access tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bare '--extender-…' cells were being typographically converted to an em dash, so the rendered flag read '—extender-enabled'. Wrapped in code so they render verbatim and in mono. Also restores the missing space before 'authzed-audit'. --- app/authzed/concepts/audit-logging/page.mdx | 36 ++++++++++--------- .../concepts/restricted-api-access/page.mdx | 34 +++++++++++------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/app/authzed/concepts/audit-logging/page.mdx b/app/authzed/concepts/audit-logging/page.mdx index c7d2bed7..1a168b35 100644 --- a/app/authzed/concepts/audit-logging/page.mdx +++ b/app/authzed/concepts/audit-logging/page.mdx @@ -177,27 +177,29 @@ Using the web dashboard, navigate to the Permission System's settings page to fi ### SpiceDB Enterprise (self-hosted) [#self-hosted] - **AuthZed Enterprise only.** The `--extender-audit-*` flags below exist in the AuthZed-licensed SpiceDB Enterprise binary. - They are not present in [SpiceDB open source](/authzed/guides/picking-a-product#open-source), which has no audit logging. + **AuthZed Enterprise only.** The `--extender-audit-*` flags below exist in the + AuthZed-licensed SpiceDB Enterprise binary. They are not present in [SpiceDB + open source](/authzed/guides/picking-a-product#open-source), which has no + audit logging. Use the following command-line flags: -| Flag | Description | Default | -| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| --extender-enabled | must be set to`authzed-audit` | | -| --extender-audit-batch-size-limit | defines the maximum number of audit events to be processed as a unit | `10000` | -| --extender-audit-buffer-size | defines the size of the audit log buffer that holds events to be processed by workers | `1000000` | -| --extender-audit-buffer-window | defines maximum amount of time events are buffered before being pushed | `1s` | -| --extender-audit-disabled-on-methods strings | list of comma-separated, fully-qualified API methods to disable events for. Watch API is always excluded (e.g. `/authzed.api.v1.PermissionsService/CheckPermission`) | | -| --extender-audit-initial-retry-interval duration | sets the first retry backoff in case of a failure to push audit events to the backend | `1s` | -| --extender-audit-max-retry-interval duration | sets the maximum backoff duration in case of failure to push events | `30s` | -| --extender-audit-retry-randomizer-factor | sets the randomization factor for the backoff duration - this helps prevent thundering herds on event push errors | `0.5` | -| --extender-audit-stream-name | defines the name of the target stream/topic (e.g. Kafka Topic, Kinesis Stream...) | `spicedb` | -| --extender-audit-target-configuration | target-type specific configuration | `[]` | -| --extender-audit-target-endpoint-url string | defines the URL of target endpoint to ingest audit events. If left unspecified, some types will try to determine automatically (e.g. AWS SDK) | | -| --extender-audit-target-type | defines the type of target to ingest audit events | `noop` | -| --extender-audit-worker-count | defines the number of worker goroutines to process audit events (default 5) | | +| Flag | Description | Default | +| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `--extender-enabled` | must be set to `authzed-audit` | | +| `--extender-audit-batch-size-limit` | defines the maximum number of audit events to be processed as a unit | `10000` | +| `--extender-audit-buffer-size` | defines the size of the audit log buffer that holds events to be processed by workers | `1000000` | +| `--extender-audit-buffer-window` | defines maximum amount of time events are buffered before being pushed | `1s` | +| `--extender-audit-disabled-on-methods` strings | list of comma-separated, fully-qualified API methods to disable events for. Watch API is always excluded (e.g. `/authzed.api.v1.PermissionsService/CheckPermission`) | | +| `--extender-audit-initial-retry-interval` duration | sets the first retry backoff in case of a failure to push audit events to the backend | `1s` | +| `--extender-audit-max-retry-interval` duration | sets the maximum backoff duration in case of failure to push events | `30s` | +| `--extender-audit-retry-randomizer-factor` | sets the randomization factor for the backoff duration - this helps prevent thundering herds on event push errors | `0.5` | +| `--extender-audit-stream-name` | defines the name of the target stream/topic (e.g. Kafka Topic, Kinesis Stream...) | `spicedb` | +| `--extender-audit-target-configuration` | target-type specific configuration | `[]` | +| `--extender-audit-target-endpoint-url` string | defines the URL of target endpoint to ingest audit events. If left unspecified, some types will try to determine automatically (e.g. AWS SDK) | | +| `--extender-audit-target-type` | defines the type of target to ingest audit events | `noop` | +| `--extender-audit-worker-count` | defines the number of worker goroutines to process audit events (default 5) | | ### Tokens in Audit Logs diff --git a/app/authzed/concepts/restricted-api-access/page.mdx b/app/authzed/concepts/restricted-api-access/page.mdx index dabbcc5c..57d03607 100644 --- a/app/authzed/concepts/restricted-api-access/page.mdx +++ b/app/authzed/concepts/restricted-api-access/page.mdx @@ -7,7 +7,10 @@ import { Callout, Tabs } from "nextra/components"; # Restricted API Access - + Restricted API Access restricts access to SpiceDB for API Tokens. @@ -38,12 +41,15 @@ SpiceDB clients must provide a Token in the Authorization header of an API reque Service Accounts can have an arbitrary number of Tokens. - We recommend deploying new Tokens before deprovisioning any old Tokens to avoid downtime. + We recommend deploying new Tokens before deprovisioning any old Tokens to + avoid downtime. #### Token Format -The entire contents of a Token is considered secret. + + The entire contents of a Token is considered secret. + Tokens come in the form of `{prefix}_{key}`. @@ -104,10 +110,11 @@ Policies are what bind Roles to a Service Account. Each policy is composed of a unique identifier for the policy itself, the principal (the target of the role assignment), and any roles being assigned. - **Policies are additive.** When multiple policies apply to the same Service Account, the resulting - permissions are the union of all permissions granted by those policies. This means a Service - Account with multiple policies will have access to any API method allowed by any of its policies. - For example, if one policy grants read access and another grants write access, the Service Account + **Policies are additive.** When multiple policies apply to the same Service + Account, the resulting permissions are the union of all permissions granted by + those policies. This means a Service Account with multiple policies will have + access to any API method allowed by any of its policies. For example, if one + policy grants read access and another grants write access, the Service Account will have both read and write access. @@ -215,16 +222,17 @@ Using the web dashboard, navigate to the Permission System's "Access" tab. Use the following command-line flags: -| Flag | Description | Default | -| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| --extender-authzed-fgam-endpoint | defines the external SpiceDB endpoint used to authorize operations for the authzed-fgam extender. If a file:// endpoint is provided, server is run embedded with static configuration | | -| --extender-authzed-fgam-preshared-key | defines the external SpiceDB preshared key used to authorize operations for the authzed-fgam extender. Ignored if endpoint is local (file://) | | -| --extender-enabled | must be set to `authzed-fgam` | | +| Flag | Description | Default | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `--extender-authzed-fgam-endpoint` | defines the external SpiceDB endpoint used to authorize operations for the authzed-fgam extender. If a file:// endpoint is provided, server is run embedded with static configuration | | +| `--extender-authzed-fgam-preshared-key` | defines the external SpiceDB preshared key used to authorize operations for the authzed-fgam extender. Ignored if endpoint is local (file://) | | +| `--extender-enabled` | must be set to `authzed-fgam` | | If you set `--extender-authzed-fgam-endpoint` to a file, it must be a YAML configuration file. - This configuration file should be treated like a secret because it contains token hashes. + This configuration file should be treated like a secret because it contains + token hashes. Here's an example showcasing the structure of static configuration: From 700c6dcac7056af4e44704eac1e80813857be42b Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:48:01 -0400 Subject: [PATCH 05/17] docs(authzed): frame Restricted API Access's self-hosted section as SpiceDB Enterprise Same trap as Audit Logging: a '### Self-Hosted' heading over extender flags, reachable by deep link, with the product scope only in the intro. Renamed with the #self-hosted anchor kept, Enterprise-only callout above the flag table. --- app/authzed/concepts/restricted-api-access/page.mdx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/authzed/concepts/restricted-api-access/page.mdx b/app/authzed/concepts/restricted-api-access/page.mdx index 57d03607..39b69033 100644 --- a/app/authzed/concepts/restricted-api-access/page.mdx +++ b/app/authzed/concepts/restricted-api-access/page.mdx @@ -218,7 +218,13 @@ The process for setting up this feature varies depending on the AuthZed product Using the web dashboard, navigate to the Permission System's "Access" tab. -### Self-Hosted +### SpiceDB Enterprise (self-hosted) [#self-hosted] + + + **AuthZed Enterprise only.** The `--extender-*` flags below exist in the + AuthZed-licensed SpiceDB Enterprise binary. They are not present in [SpiceDB + open source](/authzed/guides/picking-a-product#open-source). + Use the following command-line flags: From a4f448a3aea62d9a0f525b456475bdfe48bc0a9f Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:54:10 -0400 Subject: [PATCH 06/17] docs: re-key Nextra callouts to Sandworm tokens Warning was Tailwind yellow-700 on yellow-50, info was blue-700 on blue-100; neither is a site colour. Now: sand for warning, blue-500 for info, red-400 for error, teal for the green type, violet for important, using the same 10% tint / 50% border / full ink recipe as the product and feature pills. Light mode darkens the ink one step via relative colour syntax, with the plain token as the fallback where that syntax is unsupported. --- app/globals.css | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/globals.css b/app/globals.css index 43623b44..7b1236d1 100644 --- a/app/globals.css +++ b/app/globals.css @@ -404,3 +404,35 @@ article table td code.nextra-code { article table td:last-child { min-width: 6rem; } + +/* ── Callouts ─────────────────────────────────────────────────────────────── + Nextra colours its with stock Tailwind hues (yellow-700 text on + yellow-50, blue-700 on blue-100, …), none of which are Sandworm. Re-key each + type to the site's own tokens, in the same tint/border/ink recipe the + product and feature pills use: 10% tint, 50% border, full-strength ink. + Types are matched on Nextra's own background class since the component + exposes no type attribute. */ + +.nextra-callout { + --co: var(--blue-500); + background: hsl(var(--co) / 0.1); + border-color: hsl(var(--co) / 0.5); + color: hsl(var(--co)); +} +.nextra-callout[class*="x:bg-yellow-"] { + --co: var(--sand-300); +} +.nextra-callout[class*="x:bg-red-"] { + --co: var(--red-400); +} +.nextra-callout[class*="x:bg-green-"] { + --co: var(--teal-500); +} +.nextra-callout[class*="x:bg-purple-"] { + --co: var(--violet-500); +} +/* Light mode: the tokens are mid-lightness, so ink needs to be darker than + the border to keep body text readable on the tint. */ +html:not(.dark) .nextra-callout { + color: hsl(from hsl(var(--co)) h s calc(l - 10)); +} From 7dd7bac8947d27c8e331b46eee3411fc23f639a4 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 13:00:19 -0400 Subject: [PATCH 07/17] docs: re-key the content-review banner to Sandworm tokens Hand-picked amber and green replaced with sand (updated) and teal (new) in the same tint / border / ink recipe as callouts and pills. --- components/content-status.css | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/components/content-status.css b/components/content-status.css index 837c7312..d100ab3f 100644 --- a/components/content-status.css +++ b/components/content-status.css @@ -28,19 +28,20 @@ opacity: 0.85; color: inherit; } +/* Sandworm tokens, pill recipe (10% tint, 50% border, full ink). Light mode + darkens the ink one step; the plain token is the fallback where relative + colour syntax is unsupported. Teal = new page, sand = updated. */ .content-status.is-new { - border-color: hsl(146 45% 38% / 0.5); - background: hsl(146 45% 45% / 0.12); - color: hsl(146 55% 26%); + --cs: var(--teal-500); } .content-status.is-updated { - border-color: hsl(38 72% 45% / 0.5); - background: hsl(38 72% 50% / 0.12); - color: hsl(32 70% 30%); + --cs: var(--sand-300); } -.dark .content-status.is-new { - color: hsl(146 50% 78%); +.content-status { + border-color: hsl(var(--cs) / 0.5); + background: hsl(var(--cs) / 0.1); + color: hsl(var(--cs)); } -.dark .content-status.is-updated { - color: hsl(40 85% 78%); +html:not(.dark) .content-status { + color: hsl(from hsl(var(--cs)) h s calc(l - 10)); } From 05f55dc4901e9cf69172d844857cbdca4a90a402 Mon Sep 17 00:00:00 2001 From: Corey Thomas <125082303+Corey-T1000@users.noreply.github.com> Date: Wed, 9 Sep 2026 13:13:06 -0400 Subject: [PATCH 08/17] style: oxfmt (the repo formatter is oxfmt, not prettier) --- app/authzed/concepts/audit-logging/page.mdx | 7 ++--- .../concepts/restricted-api-access/page.mdx | 30 +++++++------------ components/product-badge.tsx | 26 ++++------------ lib/products.ts | 3 +- 4 files changed, 20 insertions(+), 46 deletions(-) diff --git a/app/authzed/concepts/audit-logging/page.mdx b/app/authzed/concepts/audit-logging/page.mdx index 1a168b35..e5ea5584 100644 --- a/app/authzed/concepts/audit-logging/page.mdx +++ b/app/authzed/concepts/audit-logging/page.mdx @@ -177,10 +177,9 @@ Using the web dashboard, navigate to the Permission System's settings page to fi ### SpiceDB Enterprise (self-hosted) [#self-hosted] - **AuthZed Enterprise only.** The `--extender-audit-*` flags below exist in the - AuthZed-licensed SpiceDB Enterprise binary. They are not present in [SpiceDB - open source](/authzed/guides/picking-a-product#open-source), which has no - audit logging. + **AuthZed Enterprise only.** The `--extender-audit-*` flags below exist in the AuthZed-licensed + SpiceDB Enterprise binary. They are not present in [SpiceDB open + source](/authzed/guides/picking-a-product#open-source), which has no audit logging. Use the following command-line flags: diff --git a/app/authzed/concepts/restricted-api-access/page.mdx b/app/authzed/concepts/restricted-api-access/page.mdx index 39b69033..680ba5c8 100644 --- a/app/authzed/concepts/restricted-api-access/page.mdx +++ b/app/authzed/concepts/restricted-api-access/page.mdx @@ -7,10 +7,7 @@ import { Callout, Tabs } from "nextra/components"; # Restricted API Access - + Restricted API Access restricts access to SpiceDB for API Tokens. @@ -41,15 +38,12 @@ SpiceDB clients must provide a Token in the Authorization header of an API reque Service Accounts can have an arbitrary number of Tokens. - We recommend deploying new Tokens before deprovisioning any old Tokens to - avoid downtime. + We recommend deploying new Tokens before deprovisioning any old Tokens to avoid downtime. #### Token Format - - The entire contents of a Token is considered secret. - +The entire contents of a Token is considered secret. Tokens come in the form of `{prefix}_{key}`. @@ -110,11 +104,10 @@ Policies are what bind Roles to a Service Account. Each policy is composed of a unique identifier for the policy itself, the principal (the target of the role assignment), and any roles being assigned. - **Policies are additive.** When multiple policies apply to the same Service - Account, the resulting permissions are the union of all permissions granted by - those policies. This means a Service Account with multiple policies will have - access to any API method allowed by any of its policies. For example, if one - policy grants read access and another grants write access, the Service Account + **Policies are additive.** When multiple policies apply to the same Service Account, the resulting + permissions are the union of all permissions granted by those policies. This means a Service + Account with multiple policies will have access to any API method allowed by any of its policies. + For example, if one policy grants read access and another grants write access, the Service Account will have both read and write access. @@ -221,9 +214,9 @@ Using the web dashboard, navigate to the Permission System's "Access" tab. ### SpiceDB Enterprise (self-hosted) [#self-hosted] - **AuthZed Enterprise only.** The `--extender-*` flags below exist in the - AuthZed-licensed SpiceDB Enterprise binary. They are not present in [SpiceDB - open source](/authzed/guides/picking-a-product#open-source). + **AuthZed Enterprise only.** The `--extender-*` flags below exist in the AuthZed-licensed SpiceDB + Enterprise binary. They are not present in [SpiceDB open + source](/authzed/guides/picking-a-product#open-source). Use the following command-line flags: @@ -237,8 +230,7 @@ Use the following command-line flags: If you set `--extender-authzed-fgam-endpoint` to a file, it must be a YAML configuration file. - This configuration file should be treated like a secret because it contains - token hashes. + This configuration file should be treated like a secret because it contains token hashes. Here's an example showcasing the structure of static configuration: diff --git a/components/product-badge.tsx b/components/product-badge.tsx index fa390868..614e0a50 100644 --- a/components/product-badge.tsx +++ b/components/product-badge.tsx @@ -26,35 +26,19 @@ type Props = { export function ProductBadge({ available, diy = [] }: Props) { const yes = PRODUCT_ORDER.filter((k) => available.includes(k)); - const build = PRODUCT_ORDER.filter( - (k) => !available.includes(k) && diy.includes(k), - ); - const missing = PRODUCT_ORDER.filter( - (k) => !available.includes(k) && !diy.includes(k), - ); + const build = PRODUCT_ORDER.filter((k) => !available.includes(k) && diy.includes(k)); + const missing = PRODUCT_ORDER.filter((k) => !available.includes(k) && !diy.includes(k)); return ( - + Available on {yes.map((k) => ( - + {PRODUCTS[k].label} ))} {build.map((k) => ( - + {PRODUCTS[k].label}