Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/materialize/concepts/permission-set-lifecycle/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ The **permission set lifecycle** describes how your application's local copy of

When you first bring a system online, you have no permission data locally.
The initial **backfill** reads the **current** state of every permission set Materialize is configured to watch and writes it into your datastore.
Once the backfill is complete, you switch to [WatchPermissionSets](../../api/watch-permission-sets) to keep that data current — see [Snapshots](./snapshots) for how the handoff stays consistent.
Once the backfill is complete, you switch to [WatchPermissionSets](../api/watch-permission-sets) to keep that data current — see [Snapshots](./snapshots) for how the handoff stays consistent.

## Stages of the lifecycle

1. **Backfill** — populate your store with the current state of every permission set. Two APIs can produce the initial backfill:
- **`DownloadPermissionSets`** (the Download API) — **recommended**. It ingests significantly faster than `LookupPermissionSets` and is the preferred path for the initial backfill.
- **[LookupPermissionSets](../../api/lookup-permission-sets)** — kept available for clients that find it easier to integrate with. Page through the stream via cursors until an iteration yields zero events. Each event carries the permission-set data to store **and** the cursor to resume from on failure.
- **[LookupPermissionSets](../api/lookup-permission-sets)** — kept available for clients that find it easier to integrate with. Page through the stream via cursors until an iteration yields zero events. Each event carries the permission-set data to store **and** the cursor to resume from on failure.
2. **Record the snapshot revision** — every backfill event includes the revision (`ZedToken`) the data was computed at. Store it transactionally alongside the data.
3. **Switch to the change stream** — once the backfill completes, open [WatchPermissionSets](../../api/watch-permission-sets) using the stored snapshot revision so no changes are missed between the backfill and live updates.
3. **Switch to the change stream** — once the backfill completes, open [WatchPermissionSets](../api/watch-permission-sets) using the stored snapshot revision so no changes are missed between the backfill and live updates.

<Callout type="warning">
The lifecycle is not only a first-run concern. You must re-run the backfill after a **breaking
Expand Down
6 changes: 3 additions & 3 deletions app/materialize/concepts/permission-sets/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ This is what makes authorization-aware search, sorting, and filtering over large

Permission sets reach your application through two complementary APIs:

- [LookupPermissionSets](../../api/lookup-permission-sets) — reads the **current** permission sets as an initial backfill. See [The permission set lifecycle](./permission-set-lifecycle).
- [WatchPermissionSets](../../api/watch-permission-sets) — streams **changes** to permission sets as relationships and schema evolve. See [Snapshots](./snapshots) for how the two stay consistent.
- [LookupPermissionSets](../api/lookup-permission-sets) — reads the **current** permission sets as an initial backfill. See [The permission set lifecycle](./permission-set-lifecycle).
- [WatchPermissionSets](../api/watch-permission-sets) — streams **changes** to permission sets as relationships and schema evolve. See [Snapshots](./snapshots) for how the two stay consistent.

## Storing permission sets

The shape of the data maps cleanly onto relational tables (a `member_to_set` and a `set_to_set` table is the most flexible model), or into a secondary index such as Elasticsearch for ACL-filtered search.
See [Syncing to a Relational Database](../../guides/relational-database) for worked examples.
See [Syncing to a Relational Database](../guides/relational-database) for worked examples.

<Callout type="info">
The fields returned by `LookupPermissionSets` and `WatchPermissionSets` are identical — you store
Expand Down
2 changes: 1 addition & 1 deletion app/materialize/concepts/snapshots/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Every piece of permission data Materialize hands you is anchored to the revision
Snapshots are what make the two Materialize APIs compose safely:

- [The initial backfill](./permission-set-lifecycle) reads a snapshot in full.
- [WatchPermissionSets](../../api/watch-permission-sets) advances that snapshot forward, delivering the deltas that move it from one revision to the next.
- [WatchPermissionSets](../api/watch-permission-sets) advances that snapshot forward, delivering the deltas that move it from one revision to the next.

## Why the revision matters

Expand Down
58 changes: 2 additions & 56 deletions lib/changed-pages.json
Original file line number Diff line number Diff line change
@@ -1,65 +1,11 @@
{
"/authzed/guides/picking-a-product": {
"/materialize/concepts/permission-set-lifecycle": {
"status": "updated"
},
"/authzed/guides/postgres-fdw": {
"status": "updated"
},
"/materialize/api/client-sdks": {
"status": "new"
},
"/materialize/api/lookup-permission-sets": {
"status": "new"
},
"/materialize/api/watch-permission-sets": {
"status": "new"
},
"/materialize/concepts/hydration": {
"status": "new"
},
"/materialize/concepts/managing-client-state": {
"status": "new"
},
"/materialize/concepts/permission-sets": {
"status": "new"
},
"/materialize/concepts/snapshots": {
"status": "new"
},
"/materialize/getting-started/limitations": {
"status": "new"
},
"/materialize/getting-started/overview": {
"status": "new"
},
"/materialize/guides/recommended-architecture": {
"status": "new"
},
"/materialize/guides/relational-database": {
"status": "new"
},
"/spicedb/best-practices": {
"status": "updated"
},
"/spicedb/concepts/querying-data": {
"status": "updated"
},
"/spicedb/concepts/read-after-write": {
"status": "updated"
},
"/spicedb/getting-started/discovering-spicedb": {
"status": "updated"
},
"/spicedb/modeling/attributes": {
"status": "updated"
},
"/spicedb/modeling/validation-testing-debugging": {
"status": "updated"
},
"/spicedb/ops/performance": {
"status": "updated"
},
"/spicedb/ops/postgres-fdw": {
"/materialize/concepts/snapshots": {
"status": "updated"
}
}
Loading