diff --git a/app/authzed/guides/picking-a-product/page.mdx b/app/authzed/guides/picking-a-product/page.mdx index e9e5bd6b..4273e316 100644 --- a/app/authzed/guides/picking-a-product/page.mdx +++ b/app/authzed/guides/picking-a-product/page.mdx @@ -13,28 +13,36 @@ This document is designed to give a high-level overview of the features supporte ## Feature Matrix -| Feature | [Open Source] | [Cloud] | [Dedicated] | [Enterprise] | -| ---------------------------- | :-----------: | :-----: | :---------: | :----------: | -| Self-Hosted | | | | | -| No-commit pricing | | | | | -| [Materialize (Early Access)] | | | | | -| [Management Dashboard] | | | | | -| [Private Networking] | DIY | | | DIY | -| [Workload Isolation] | DIY | | | DIY | -| [Automated Updates] | DIY | | | DIY | -| [SOC2 Compliance] | DIY | | | DIY | -| [Audit Logging] | | | | | -| [Rate Limiting] | | | | | -| [Multi-Region Deployments] | DIY | | | DIY | -| [Security Embargo] | | | | | -| [Restricted API Access] | DIY | | | | -| [Expedited Support] | | | | | + + +| Feature | [Open Source] | [Cloud] | [Dedicated] | [Enterprise] | +| -------------------------------- | :-----------: | :--------: | :---------: | :----------: | +| Self-Hosted | | | | | +| No-commit pricing | | | | | +| **[Materialize]** | | | | | +| ↳ [Accelerated Queries] | | | | | +| ↳ [Event Streams (Early Access)] | | | | | +| [Management Dashboard] | | | | | +| [Private Networking] | DIY | | | DIY | +| [Workload Isolation] | DIY | | | DIY | +| [Automated Updates] | DIY | | | DIY | +| [SOC2 Compliance] | DIY | | | DIY | +| [Audit Logging] | | | | | +| [Rate Limiting] | | | | | +| [Multi-Region Deployments] | DIY | | | DIY | +| [Security Embargo] | | | | | +| [Restricted API Access] | DIY | | | | +| [Expedited Support] | | | | | + + [Cloud]: #cloud [Dedicated]: #dedicated [Enterprise]: #enterprise [Open Source]: #open-source -[Materialize (Early Access)]: /materialize/getting-started/overview +[Materialize]: /materialize/getting-started/overview +[Accelerated Queries]: /materialize/getting-started/overview#accelerated-queries +[Event Streams (Early Access)]: /materialize/getting-started/overview#event-streams [Audit Logging]: ../concepts/audit-logging [Automated Updates]: ../concepts/update-channels [Management Dashboard]: ../concepts/management-dashboard diff --git a/app/materialize/getting-started/overview/page.mdx b/app/materialize/getting-started/overview/page.mdx index de97d7d8..993dcaa7 100644 --- a/app/materialize/getting-started/overview/page.mdx +++ b/app/materialize/getting-started/overview/page.mdx @@ -12,7 +12,7 @@ AuthZed Materialize takes inspiration from the Leopard index component described Much like the concept of a materialized view in relational databases, AuthZed Materialize is a service that you configure with a list of permissions that you want it to precompute, and it will calculate how those permissions change after relationships are written (specifically, when those relationships affect a subject's membership in a permission set or a set's permission on a specific resource), or when a new schema is written. -Materialize puts that precomputed data to work in two ways: **Accelerated Queries** and **Event Streams**, both currently in early access. Every other piece of Materialize content belongs to one of these two features. Look for badges at the top of the page, which link back to the feature it belongs to. +Materialize puts that precomputed data to work in two ways: **Accelerated Queries**, generally available to AuthZed [Dedicated] users, and **Event Streams**, currently in early access. Every other piece of Materialize content belongs to one of these two features. Look for badges at the top of the page, which link back to the feature it belongs to. - Accelerated Queries is available to users of AuthZed [Dedicated] as part of an early access - program. Don't hesitate to get in touch with your AuthZed account team if you would like to - participate. + Accelerated Queries is generally available to users of AuthZed [Dedicated]. Get in touch with your + AuthZed account team to get started. Accelerated Queries use Materialize's precomputed permissions cache to answer the SpiceDB queries your application already makes, without changing how you call SpiceDB: diff --git a/app/spicedb/getting-started/faq/page.mdx b/app/spicedb/getting-started/faq/page.mdx index 48d1df2e..779ed039 100644 --- a/app/spicedb/getting-started/faq/page.mdx +++ b/app/spicedb/getting-started/faq/page.mdx @@ -59,9 +59,9 @@ There are three approaches for filtering resources based on whether users have a 2. **CheckBulkPermissions** - Use when accessible resources are too large for LookupResources. Fetch a page of candidate results from your database, then call `CheckBulkPermissions` to determine which ones the user can access. Keep iterating until you have a full page of permitted results. This works well with cursor-based pagination and search interfaces. -3. **Materialize** (Early Access) - For maximum scalability with large datasets or high traffic. Materialize watches permission changes in SpiceDB and maintains a local denormalized view of user permissions, allowing you to use simple database JOINs for filtering. +3. **Materialize's Event Streams** (Early Access) - For maximum scalability with large datasets or high traffic. Materialize watches permission changes in SpiceDB and maintains a local denormalized view of user permissions, allowing you to use simple database JOINs for filtering. -Choose based on your scale: start with LookupResources, move to CheckBulkPermissions when needed, and consider Materialize for the highest performance requirements. [Learn more] +Choose based on your scale: start with LookupResources, move to CheckBulkPermissions when needed, and consider Materialize's Event Streams for the highest performance requirements. [Learn more] [Learn more]: ../modeling/protecting-a-list-endpoint diff --git a/app/spicedb/modeling/protecting-a-list-endpoint/page.mdx b/app/spicedb/modeling/protecting-a-list-endpoint/page.mdx index 5cbb8461..f934d60e 100644 --- a/app/spicedb/modeling/protecting-a-list-endpoint/page.mdx +++ b/app/spicedb/modeling/protecting-a-list-endpoint/page.mdx @@ -93,8 +93,9 @@ to the point where checking them via bulk check is relatively easy. ## Using Materialize - Materialize is currently in Early Access. Additional documentation and product information will be - coming soon. In the meantime, if you're interested, [schedule a call!][Schedule Call] + This pattern uses Materialize's Event Streams feature, currently in early access for AuthZed + Dedicated users. See the [Materialize overview] to learn more, or [schedule a call!][Schedule + Call] [Authzed Materialize] is Authzed's version of the [Leopard cache] referenced in the Zanzibar paper, which provides a denormalized view @@ -113,6 +114,7 @@ under the above two approaches, we recommend giving Authzed Materialize a try. [Schedule Call]: https://authzed.com/call [Leopard cache]: https://authzed.com/zanzibar/2IoYDUFMAE:0:T +[Materialize overview]: /materialize/getting-started/overview#event-streams ## Other Considerations diff --git a/components/feature-icon.css b/components/feature-icon.css index 6cea4f29..55b81aba 100644 --- a/components/feature-icon.css +++ b/components/feature-icon.css @@ -35,3 +35,23 @@ html.dark .feature-yes svg { .feature-no svg { stroke: hsl(351 55% 53%); } + +/* Absent — muted dash, no disc. Reads as "nothing here" rather than "no". */ +.feature-absent { + color: hsl(280 4% 62%); + font-size: 1.125rem; + line-height: 1; +} +html.dark .feature-absent { + color: hsl(279 9% 40%); +} + +.feature-sr { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; +} diff --git a/components/feature-icon.tsx b/components/feature-icon.tsx index a5222451..19d5e64b 100644 --- a/components/feature-icon.tsx +++ b/components/feature-icon.tsx @@ -2,7 +2,13 @@ import "./feature-icon.css"; /* Feature-matrix marks for docs tables — Lucide check / x glyphs in Sandworm colors, matching the marketing pricing comparison. Theme-aware styling lives - in feature-icon.css. Used in MDX as / (mdx-components.ts). */ + in feature-icon.css. Used in MDX as / / + (mdx-components.ts). + + is a red cross: a real negative (a permission check that denied). + is a muted dash: a tier that simply doesn't carry a line. In a + product matrix an absence is not a failure, so it should not read as one. + Same rule as the marketing pricing/support comparison (SupportComparison). */ export function Yes() { return ( @@ -41,3 +47,12 @@ export function No() { ); } + +export function Absent() { + return ( + + + Not included + + ); +} diff --git a/components/feature-matrix.css b/components/feature-matrix.css new file mode 100644 index 00000000..fb59df8c --- /dev/null +++ b/components/feature-matrix.css @@ -0,0 +1,132 @@ +/* Feature matrix — the docs twin of authzed.com's pricing/Support comparison + tables (web: pricing/TableGroup.tsx + SupportComparison.tsx). Unlayered so + it wins over Nextra's `x:` table utilities without !important. */ + +.feature-matrix { + --fm-rule: hsl(280 5% 84%); + --fm-hover: hsl(300 8% 96%); + --fm-label: hsl(280 6% 22%); + --fm-head: hsl(280 10% 12%); + --fm-muted: hsl(280 4% 48%); + --fm-link-rule: hsl(280 5% 72%); + --fm-link: hsl(var(--sand-300)); + margin-top: 1.5rem; + overflow-x: auto; +} +html.dark .feature-matrix { + --fm-rule: hsl(279 9% 22%); + --fm-hover: hsl(279 12% 11%); + --fm-label: hsl(280 6% 82%); + --fm-head: hsl(300 6% 95%); + --fm-muted: hsl(280 4% 55%); + --fm-link-rule: hsl(279 8% 36%); + --fm-link: hsl(var(--sand-300)); +} + +.feature-matrix table { + display: table; + width: 100%; + margin: 0; + padding: 0; + border-collapse: collapse; + overflow: visible; +} + +.feature-matrix tr { + margin: 0; + padding: 0; + border: 0; + border-top: 1px solid var(--fm-rule); + border-bottom: 1px solid var(--fm-rule); + background: transparent; +} +.feature-matrix thead tr { + border-top: 0; +} +.feature-matrix tbody tr:hover { + background: var(--fm-hover); +} + +.feature-matrix th, +.feature-matrix td { + margin: 0; + padding: 1rem 0.5rem; + border: 0; + vertical-align: middle; +} + +/* Column headers: plain text, not link-orange. The link still works. */ +.feature-matrix thead th { + padding-top: 0.75rem; + padding-bottom: 1rem; + font-family: inherit; + font-size: 1.125rem; + font-weight: 400; + color: var(--fm-head); + text-align: center; +} +.feature-matrix thead th:first-child { + padding-left: 1.5rem; + text-align: left; +} +.feature-matrix thead th a, +.feature-matrix tbody td:first-child a { + color: inherit; + font-weight: inherit; + text-decoration: underline; + text-decoration-color: var(--fm-link-rule); + text-decoration-thickness: 1px; + text-underline-offset: 0.3em; + transition: + color 120ms, + text-decoration-color 120ms; +} +.feature-matrix thead th a:hover, +.feature-matrix tbody td:first-child a:hover { + color: var(--fm-link); + text-decoration-color: currentColor; +} + +/* Row labels: mono, like the web tables. Links stay links, quietly. */ +.feature-matrix tbody td:first-child { + padding-left: 1.5rem; + font-family: ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace; + font-size: 0.875rem; + color: var(--fm-label); + text-align: left; + white-space: nowrap; +} +/* Nextra appends an arrow icon to external links; keep it, just quiet it. */ +.feature-matrix tbody td:first-child a svg, +.feature-matrix thead th a svg { + opacity: 0.6; +} + +/* Value cells: centred, ruled between columns, never against the label. */ +.feature-matrix tbody td:not(:first-child) { + border-left: 1px solid var(--fm-rule); + font-size: 0.875rem; + text-align: center; + color: var(--fm-label); +} +.feature-matrix tbody td:not(:first-child) .feature-mark { + vertical-align: middle; +} + +/* Group-label row: a bold first cell and nothing else in the row. + Reads as a section header (web: RowGroup title), not a scored feature. */ +.feature-matrix tbody tr:has(> td:first-child > strong) { + background: transparent; +} +.feature-matrix tbody tr:has(> td:first-child > strong) td:first-child { + padding-top: 1rem; + padding-bottom: 0.75rem; + font-size: 1rem; + font-weight: 300; +} +.feature-matrix tbody tr:has(> td:first-child > strong) strong { + font-weight: inherit; +} +.feature-matrix tbody tr:has(> td:first-child > strong) td:not(:first-child) { + border-left-color: transparent; +} diff --git a/components/feature-matrix.tsx b/components/feature-matrix.tsx new file mode 100644 index 00000000..349d09dd --- /dev/null +++ b/components/feature-matrix.tsx @@ -0,0 +1,12 @@ +import "./feature-matrix.css"; +import type { ReactNode } from "react"; + +/* Wraps a markdown feature matrix so it reads like the pricing and Support + comparison tables on authzed.com instead of Nextra's default zebra table: + mono row labels, horizontal rules only, a group-label row for a feature + family (a bold first cell with the rest empty), row hover, plain-text + column headers. Used in MDX as …table… + (mdx-components.ts). Styling lives in feature-matrix.css. */ +export function FeatureMatrix({ children }: { children: ReactNode }) { + return
{children}
; +} diff --git a/lib/changed-pages.json b/lib/changed-pages.json index 161367dc..9052da4c 100644 --- a/lib/changed-pages.json +++ b/lib/changed-pages.json @@ -1,11 +1,14 @@ { - "/authzed/concepts/deployments": { - "status": "new" + "/authzed/guides/picking-a-product": { + "status": "updated" + }, + "/materialize/getting-started/overview": { + "status": "updated" }, - "/authzed/concepts/multi-region": { + "/spicedb/getting-started/faq": { "status": "updated" }, - "/authzed/guides/cloud": { + "/spicedb/modeling/protecting-a-list-endpoint": { "status": "updated" } } diff --git a/lib/materialize-features.ts b/lib/materialize-features.ts index aab8454f..e385caae 100644 --- a/lib/materialize-features.ts +++ b/lib/materialize-features.ts @@ -21,11 +21,10 @@ export const FEATURES = { export type FeatureKey = keyof typeof FEATURES; -/* Every feature is in early access today, so the note's text doesn't vary. - It's per-feature anyway because the note is colour-matched to its pill — - and because these will go GA on different dates. */ +/* Per-feature because the note is colour-matched to its pill, and because + these go GA on different dates — Accelerated Queries reached GA first. */ export const EARLY_ACCESS: Record = { - "accelerated-queries": true, + "accelerated-queries": false, "event-streams": true, }; diff --git a/mdx-components.ts b/mdx-components.ts index 699f653a..2d8cdbf1 100644 --- a/mdx-components.ts +++ b/mdx-components.ts @@ -1,7 +1,8 @@ import { useMDXComponents as getDocsMDXComponents } from "nextra-theme-docs"; import type { Component } from "react"; -import { Yes, No } from "@/components/feature-icon"; +import { Yes, No, Absent } from "@/components/feature-icon"; import { FeatureBadge } from "@/components/feature-badge"; +import { FeatureMatrix } from "@/components/feature-matrix"; const docsComponents = getDocsMDXComponents(); @@ -9,6 +10,8 @@ export const useMDXComponents = (components?: Component) => ({ ...docsComponents, Yes, No, + Absent, FeatureBadge, + FeatureMatrix, ...components, });