TIP
Original: View on authzed.com 中文版: 查看中文版
Composable Schemas
To facilitate schema organization and cross-team collaboration, zed version v0.27.0 introduced a schema compilation command enabling schema modularization:
zed schema compile root.zedThis command combines schemas spread across multiple files into a single unified schema.
Example Structure
root.zed
use import
use partial
import "./subjects.zed"
partial view_partial {
relation user: user
permission view = user
}
definition resource {
...view_partial
relation organization: organization
permission manage = organization
}subjects.zed
definition user {}
definition organization {}Compiled Output
definition user {}
definition organization {}
definition resource {
relation user: user
permission view = user
relation organization: organization
permission manage = organization
}The compiled output can be understood by SpiceDB's WriteSchema API.
Core Concepts
Three new syntax elements are introduced: import statements, partial declarations, and partial references.
Breaking Changes
use import and use partial
zed version v0.36.0
As of v0.36.0, enabling import and partial syntax requires corresponding use flags:
use import
use partial
import "foo.zed"
partial something {}The use flags are required only in files using those keywords. Imported files without their own import or partial syntax don't need flags, though their presence causes no error.
New Keywords
zed version v0.27.0 to v0.35.0
INFO
This is superseded by use import and use partial above.
The composable schema compiler introduces breaking changes relative to SpiceDB's internal WriteSchema compiler. While new SpiceDB versions shouldn't break existing schemas, the compiler introduces new keywords, potentially causing compilation failures for previously valid schemas.
import and partial became keywords, so permissions or relations with those names cannot be compiled. Reserved keywords include use, and, or, and not. Unexpected TokenTypeKeyword errors likely stem from this issue. Reserved keywords are documented in the lexer definition.
Import Statements
Import statements decompose schemas along top-level declaration boundaries.
root.zed
use import
// An import keyword followed by a quoted relative filepath
import "./one.zed"
// Note that a bare filename works as a relative path
import "two.zed"
// The imports are included by the compilation process, which means that
// they can be referenced by other definitions
definition resource {
relation user: user
relation organization: organization
permission view = user + organization
}one.zed
definition user {}two.zed
definition organization {}Good to Know
- Import references must be within the folder where
zedis invoked. - Import cycles are treated as errors.
- All definitions in all imported files are pulled in. Any duplicate definitions will cause an error.
Partials
Partial declarations and references provide schema decomposition across definition boundaries.
Partial Declarations
A partial declaration is a top-level block declared using the partial keyword. It can contain relations, permissions, and partial references like a definition block, but contents must be referenced by a partial reference to appear in the compiled schema.
use partial
partial view_partial {
...some_other_partial
relation user: user
permission view = user
}Good to Know
- Any unreferenced partial is ignored during compilation.
- Partial declarations can contain partial references, enabling partial composition.
Partial References
A partial reference includes relations and permissions from a partial, functioning similarly to JavaScript spread syntax or Python dictionary unpacking.
This syntax:
use partial
partial view_partial {
relation viewer: user
permission view = viewer
}
partial edit_partial {
relation editor: user
permission edit = editor
}
definition resource {
...view_partial
...edit_partial
}is equivalent to:
definition resource {
relation user: user
permission view = user
relation editor: user
permission edit = editor
}Good to Know
- Duplicate relations and permissions from partial references are treated as errors.
- Circular references between partials are treated as errors.
- Only partial declarations can be referenced. Attempting to reference other declaration types (definitions, caveats) with partial references results in an error.
- A partial can be referenced multiple times, and partials or definitions can contain any number of partial references.
An Example Workflow
- Make a change to your multi-file schema
- Run
zed validateto ensure changes are valid - Make a PR to your schema repository
- CI runs
zed validateagain
Then on merge:
- CI runs
zed schema compile - CI calls SpiceDB's WriteSchema API with the compiled schema