pub struct IssueRequest {Show 13 fields
pub sub: String,
pub client_id: String,
pub ttl: Duration,
pub jti: Option<Ulid>,
pub entity_type: Option<EntityType>,
pub admin: bool,
pub caps: Vec<String>,
pub act: Option<Act>,
pub cid: Option<String>,
pub sv: Option<u64>,
pub active_ppnum: Option<String>,
pub scopes: Vec<String>,
pub sid: Option<String>,
}Fields§
§sub: StringSubject — the principal the token is about (RFC 7519 §4.1.2).
PAS-issued human tokens carry ppnum_id (ULID); AI-agent tokens
carry the agent’s ULID. Never empty.
client_id: Stringclient_id — the OAuth client whose credentials authorized this
token (RFC 9068 §2.2). 1st-party flows use "ppoppo-internal";
External Developer flows use the registered OAuth client_id.
ttl: DurationTime-to-live from now. The engine computes exp = iat + ttl and
emits both. Per-profile cap (24h access / 200d refresh) is
enforced via M19 on the verify side.
jti: Option<Ulid>Optional caller-supplied jti. When None, engine::encode::issue
generates a fresh ULID at issuance time. Tests pin a known ULID
so assertions can match by exact value.
entity_type: Option<EntityType>entity_type — identity class of sub (M40). Absent on
1st-party OTP/passkey flows. Typed, so a mint site cannot emit a
value this crate’s own verifier would reject as forgery — the
emitter⊆admitted half of the K8 reachability invariant is held
by the type rather than by review.
admin: booladmin — issue-time admin gate flag (M44). When true, the
verifier additionally requires active_ppnum (or sub band
fallback) to fall in an admin-allocated band — defense in depth
against forged tokens with a stolen signing key.
caps: Vec<String>caps — capability list (M41). Default [] is the default-deny
surface contract: a token with no capabilities cannot perform any
privileged operation. Engine validates only that the wire shape
is an array of strings; semantic enforcement is per-surface.
act: Option<Act>act (RFC 8693 §4.1) — the acting party, set on tokens minted via
Token Exchange flows to record who is driving this session. Audit
logs key off it, and it is half of the delegation predicate
(entity_type == Human && act.is_some()).
Chain depth is the nesting depth — there is no separate depth claim to keep in step with it, and the engine bounds that nesting (M43) on verify.
cid: Option<String>cid — WebAuthn credential id that authenticated this session
(passkey path only). Enables session-to-credential provenance for
forensic analysis and selective-session-kill flows. Absent on
every non-passkey path so audit logs distinguish authentication
methods without a per-row lookup.
sv: Option<u64>sv — per-account session_version epoch snapshot. Validators
compare token.sv >= cached(sv:{sub}) and reject stale tokens; the
counter (on ppnums.session_version) bumps inside a revocation TX
(break-glass / LogoutAll / agent disconnect), invalidating all prior
tokens within the consumer cache TTL. Carried by Human session
tokens AND by AI-agent client_credentials tokens minted via PAS’s
AgentService.IssueToken (the AI-agent kill-switch). Absent on
Token-Exchange (delegated / exchange) tokens — deferred slices — so
the engine check_epoch gate short-circuits for those.
active_ppnum: Option<String>active_ppnum — display ppnum (e.g. 123-1234-5678). UI surfaces
render this; sub is the immutable ULID and is the authorization
axis. Absent on tokens that don’t represent a human-facing
session (raw machine tokens).
scopes: Vec<String>scopes — OAuth scope list (M42). Engine bounds the array to ≤ 256
entries (RFC 8725-adjacent — bound the per-token audit surface).
Default [] is “no externally-granted scope”; 1st-party flows
emit a non-empty list (profile, email, etc).
sid: Option<String>sid — the issuer’s session identifier (M36, Phase 5). When set,
the verifier’s cfg.session_revocation::is_active(sub, sid) query
gates token admission against that session’s liveness — deletion
= revocation per STS_JWT_DETAILS_MITIGATION §E. PAS issuance sets
this to the refresh-token family_id on every 1st-party session
path; AI-agent / machine / OAuth flows leave it unset and the
verifier short-circuits the gate. Wire shape: ULID string when
present.
Implementations§
Source§impl IssueRequest
impl IssueRequest
Sourcepub fn new(
sub: impl Into<String>,
client_id: impl Into<String>,
ttl: Duration,
) -> Self
pub fn new( sub: impl Into<String>, client_id: impl Into<String>, ttl: Duration, ) -> Self
Construct a new request with the required fields. Domain claim
fields default to “absent / empty / 0 / false” — every emission
is opt-in via a with_* builder, so a caller who forgets to set
admin cannot accidentally mint an admin token.
Sourcepub fn with_jti(self, jti: Ulid) -> Self
pub fn with_jti(self, jti: Ulid) -> Self
Pin a specific jti instead of letting the engine generate one.
Test-only escape hatch — production paths should never override.
Sourcepub fn with_entity_type(self, entity_type: EntityType) -> Self
pub fn with_entity_type(self, entity_type: EntityType) -> Self
Set entity_type (M40).
Takes EntityType, not a string: the verifier rejects any
value outside the whitelist as forgery, so a mint site that
could name one would be building a token this crate refuses.
Callers holding a wider domain enum (PAS’s 5-value
ppnums.entity_type) must map it explicitly and decide what to
do with the values that have no credential flow — the compiler
will not let that mapping be silently total.
Sourcepub fn with_admin(self, admin: bool) -> Self
pub fn with_admin(self, admin: bool) -> Self
Set the admin gate flag (M44). Combined with active_ppnum band
check on the verify side, this is the issue-time half of the
admin-token defense in depth.
Sourcepub fn with_caps(self, caps: Vec<String>) -> Self
pub fn with_caps(self, caps: Vec<String>) -> Self
Set the capability list (M41). An empty list (the default) means no privileged capabilities; surface code MUST positive-check.
Sourcepub fn with_act(self, act: Act) -> Self
pub fn with_act(self, act: Act) -> Self
Set the acting party (act, RFC 8693 §4.1). Token Exchange flows
record here who is driving the session.
Takes Act rather than a bare identifier so a mint site cannot
express “delegation happened” without naming the actor — the two
were separable while the claim was a flat string plus a depth
counter, and that separability is what made the chain length
forgeable.
Sourcepub fn with_credential_id(self, credential_id: impl Into<String>) -> Self
pub fn with_credential_id(self, credential_id: impl Into<String>) -> Self
Set the WebAuthn credential id (cid). Call this only on the
passkey issuance path; other paths MUST leave it unset so audit
logs distinguish authentication methods without a per-row lookup.
Sourcepub fn with_session_version(self, sv: u64) -> Self
pub fn with_session_version(self, sv: u64) -> Self
Set the per-account session_version epoch snapshot. Called by the
Human session path and by PAS’s AgentService.IssueToken (ai_agent
client_credentials), reading ppnums.session_version. Token-Exchange
(delegated / exchange) paths leave it unset — deferred slices — and
the verifier’s check_epoch gate short-circuits on absent sv.
Sourcepub fn with_active_ppnum(self, active_ppnum: impl Into<String>) -> Self
pub fn with_active_ppnum(self, active_ppnum: impl Into<String>) -> Self
Set the display ppnum (active_ppnum). UI surfaces render this;
sub remains the immutable ULID for authorization decisions.
Sourcepub fn with_scopes(self, scopes: Vec<String>) -> Self
pub fn with_scopes(self, scopes: Vec<String>) -> Self
Set the OAuth scope list (M42). Engine bounds the array to ≤ 256 entries on the verify side.
Sourcepub fn with_sid(self, sid: impl Into<String>) -> Self
pub fn with_sid(self, sid: impl Into<String>) -> Self
Set the issuer’s session id (sid claim, M36 — Phase 5). Call
this only on issuance paths bound to a session (in PAS: the
1st-party Human paths that own a refresh-token family — CLI
handoff / magic-link / passkey / refresh-cycle, where the value
is that family_id); AI-agent, machine and OAuth paths MUST
leave it unset so the verifier short-circuits the
session-revocation gate. The verifier compares (sub, sid)
against the substrate; deletion = revocation per
STS_JWT_DETAILS_MITIGATION §E.
Trait Implementations§
Source§impl Clone for IssueRequest
impl Clone for IssueRequest
Source§fn clone(&self) -> IssueRequest
fn clone(&self) -> IssueRequest
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more