Skip to main content

IssueRequest

Struct IssueRequest 

Source
pub struct IssueRequest {
Show 14 fields pub sub: String, pub client_id: String, pub ttl: Duration, pub jti: Option<Ulid>, pub account_type: Option<String>, pub admin: bool, pub caps: Vec<String>, pub delegator: Option<String>, pub dlg_depth: u8, 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.

§account_type: Option<String>

account_type — principal class (M40). Whitelist {human, ai_agent} enforced verifier-side; absent for legacy tokens. PAS sets "human" on user-facing flows and "ai_agent" on client_credentials.

§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.

§delegator: Option<String>

delegator — delegating principal’s ppnum_id (M40-adjacent). Set on tokens minted via Token Exchange flows to record who authorized the delegated session. Audit logs key off this field. (Wire name: delegator; the earlier actor name was retired — RFC 8693 reserves actor for token-exchange chain semantics that don’t apply here.)

§dlg_depth: u8

dlg_depth — delegation chain depth (M43). 0 = original principal, each Token Exchange step increments by 1. Engine rejects > 4 to bound the audit-trail explosion of arbitrarily deep delegation. u8 is intentional: there is no scenario where depth ≥ 256.

§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 snapshot (Human path only). Validators compare token.sv >= cached(sv:{sub}) and reject stale tokens; the counter bumps inside the break-glass TX, invalidating all prior tokens within the consumer cache TTL. Absent on AI-agent and delegated tokens (no break-glass mechanism).

§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 — session row id (M36, Phase 5). When set, the verifier’s cfg.session_revocation::is_active(sub, sid) query gates token admission against user_sessions(sub, sid) row liveness — row deletion = revocation per STANDARDS_JWT_DETAILS_MITIGATION §E. PAS issuance sets this on every Human-path token bound to a session row; AI-agent / machine flows leave it unset and the verifier short-circuits the gate. Wire shape: ULID string when present (matches user_sessions.session_id PK).

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_account_type(self, account_type: impl Into<String>) -> Self

Set account_type (M40). PAS issuance paths pass "human" or "ai_agent"; the verifier’s whitelist (Phase 4 commit 4.2) rejects anything else.

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_delegator(self, delegator: impl Into<String>) -> Self

Set the delegating principal’s ppnum_id (M40-adjacent). Token Exchange flows record the human authorizer here.

Source

pub fn with_dlg_depth(self, dlg_depth: u8) -> Self

Set the delegation chain depth (M43). 0 = direct, increments by 1 per Token Exchange step; engine bounds at 4.

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 (Human entity path only). AI-agent and delegated paths MUST leave it unset — they have no break-glass mechanism, and emitting sv = 0 would lock those tokens out the moment the human originator break-glasses.

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 session row id (sid claim, M36 — Phase 5). Call this only on issuance paths bound to a user_sessions row (Human magic-link / passkey / refresh-cycle); AI-agent and machine paths MUST leave it unset so the verifier short-circuits the session-revocation gate. The verifier compares (sub, sid) against the substrate; row deletion = revocation per STANDARDS_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<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> 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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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