Skip to main content

IssueRequest

Struct IssueRequest 

Source
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: String

Subject — 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: String

client_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: Duration

Time-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: bool

admin — 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

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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

Source§

fn clone(&self) -> IssueRequest

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for IssueRequest

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more