pub struct Claims {
pub sub: String,
pub exp: u64,
pub iat: u64,
pub iss: String,
pub roles: Vec<String>,
pub email: Option<String>,
pub node_id: Option<String>,
pub scopes: Vec<TokenScope>,
pub jti: Option<String>,
}Expand description
JWT claims used by every protected endpoint.
node_id is Some only on node JWTs — tokens issued by the leader
during cluster join with roles: ["node"] so a node can authenticate
to its peers’ internal endpoints distinct from any user identity.
All other JWT issuers leave it None.
Fields§
§sub: StringSubject — user id, api-key id, or "node:{node_id}" for node JWTs.
exp: u64Expiration time (Unix seconds).
iat: u64Issued at (Unix seconds).
iss: StringIssuer (canonically "zlayer"; federation will use a cluster-id form).
roles: Vec<String>Role claims, e.g. ["admin"], ["operator"], ["node"].
#[serde(default)] preserves back-compat with tokens minted before
the field existed.
email: Option<String>Email — embedded for session JWTs so the manager UI doesn’t have to round-trip to the user store on every request.
node_id: Option<String>Cluster-wide node UUID. Some only for JWTs minted by the
leader at cluster-join time (where roles contains "node").
All other token kinds leave this None.
scopes: Vec<TokenScope>Least-privilege scope grants baked into the token. Empty for human /
admin / node tokens (whose authority comes from roles); non-empty for
scoped access tokens minted for containers, jobs, or CI runners. When
non-empty, the token is authorized for a request only if some scope
TokenScope::satisfies it (an admin role still short-circuits).
#[serde(default)] keeps back-compat with pre-scope tokens.
jti: Option<String>Token id — the revocation handle. Some only on managed scoped tokens
that have a crate::storage::StoredAccessToken record; the auth layer
rejects the token if its jti has been revoked. Human/node tokens leave
this None and skip the revocation lookup (stateless fast path).
Implementations§
Source§impl Claims
impl Claims
Sourcepub fn new(
subject: impl Into<String>,
expiry: Duration,
roles: Vec<String>,
email: Option<String>,
) -> Self
pub fn new( subject: impl Into<String>, expiry: Duration, roles: Vec<String>, email: Option<String>, ) -> Self
Create new claims.
node_id is left None; node JWTs are constructed via struct
literal at the cluster-join site.
§Panics
Panics if the system clock is before the Unix epoch.
Sourcepub fn new_scoped(
subject: impl Into<String>,
expiry: Duration,
roles: Vec<String>,
scopes: Vec<TokenScope>,
jti: impl Into<String>,
) -> Self
pub fn new_scoped( subject: impl Into<String>, expiry: Duration, roles: Vec<String>, scopes: Vec<TokenScope>, jti: impl Into<String>, ) -> Self
Create claims for a scoped access token: an attenuated bearer carrying
scopes and a jti revocation handle. roles is usually empty (or a
non-admin marker); authority comes from scopes.
§Panics
Panics if the system clock is before the Unix epoch.
Sourcepub fn is_expired(&self) -> bool
pub fn is_expired(&self) -> bool
Sourcepub fn is_scoped(&self) -> bool
pub fn is_scoped(&self) -> bool
Whether this token is a scoped access token (carries embedded scopes).
Sourcepub fn satisfies(
&self,
resource_kind: &str,
resource_id: Option<&str>,
level: PermissionLevel,
) -> bool
pub fn satisfies( &self, resource_kind: &str, resource_id: Option<&str>, level: PermissionLevel, ) -> bool
Whether the token authorizes level access to
(resource_kind, resource_id).
An admin role short-circuits to true. Otherwise authorization is
granted iff some embedded TokenScope satisfies the request. A token
with no scopes and no admin role returns false here — non-scoped
human authority is decided by role/permission checks elsewhere, not by
this method.