Internet-Draft OAuth Mission Status August 2026
McGuinness Expires 22 February 2027 [Page]
Workgroup:
Web Authorization Protocol
Internet-Draft:
draft-mcguinness-oauth-mission-status-latest
Published:
Intended Status:
Standards Track
Expires:
Author:
K. McGuinness
Independent

Mission Status and Lifecycle for OAuth 2.0

Abstract

The Mission-Bound Authorization for OAuth 2.0 profile binds issued authority to a durable, human-approved Mission and gates issuance on Mission state, but it observes Mission state only through token lifetime and optional token introspection. This document defines the Mission state-management surfaces it defers: the Mission Status operation (keyed by mission_id) with signed responses, the Mission projection for token introspection, the Mission Lifecycle endpoint with revoke, suspend, resume, complete, and discharge operations, the suspended and completed states with the consolidated lifecycle state machine this profile owns, and revocation-propagation guidance. It also defines Mission completion at the entry grain: terminal_when, a completion condition met when an authenticated discharge command or trusted deployment-internal adjudication commits that the task an entry was granted for is done. Each capability is independently optional; an implementation can adopt any subset, and one that adopts none remains a conforming issuance profile.

About This Document

This note is to be removed before publishing as an RFC.

The latest revision of this draft can be found at https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission-status.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-mcguinness-oauth-mission-status/.

Source for this draft and an issue tracker can be found at https://github.com/mcguinness/mission-bound-authorization.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 22 February 2027.

Table of Contents

1. Introduction

The issuance profile [I-D.draft-mcguinness-oauth-mission] makes a Mission a first-class OAuth artifact: a structured, human-approved, integrity-bound task whose authority bounds and outlives every token an agent derives. It is, by design, a minimum-viable issuance layer. It gates derivation on Mission state, carries the mission claim on every derived token, and offers only OPTIONAL token introspection ([I-D.draft-mcguinness-oauth-mission], Section "Mission State via Token Introspection") as a way for a Resource Server to observe Mission state. It names this profile for the canonical Mission Status surface (keyed by mission_id) and its signed status evidence, and defers a standardized management endpoint for lifecycle transitions to this document.

This document specifies those surfaces as optional extensions that build on the issuance profile. The capabilities are:

Each capability is independently optional. An implementation states which it supports through the metadata of Section 9 and the conformance language of Section 10. An implementation that supports none of them is unaffected and remains a conforming issuance profile.

This document does not restate the issuance profile. The Mission Intent, authority derivation, the mission_resource_access authorization details type, the mission claim, the integrity anchors, Mission-bound token issuance, the subset rule, and lifecycle gating are all defined in [I-D.draft-mcguinness-oauth-mission] and are referenced, not re-specified, here.

2. Conventions and Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

This document uses the terms defined in the issuance profile [I-D.draft-mcguinness-oauth-mission], in particular Mission, Mission Issuer (the Mission issuer: in this document's OAuth binding the Authorization Server; a standalone Mission Issuer, the Mission Authority Server [I-D.draft-mcguinness-mission-authority-server], serves these surfaces with the same semantics; the AAuth Person Server plays the same role for its native missions through its own AAuth-native management surface [I-D.draft-mcguinness-mission-aauth]), Authority Set, the mission claim, mission_id, and the mission_resource_access authorization details type. Resource AS is used as defined in the cross-domain companion [I-D.draft-mcguinness-oauth-mission-cross-domain]. It additionally uses:

Mission Status Response:

A signed payload returned by the dedicated Mission Status operation (Section 3), reporting a Mission's current state and the audience-scoped evidence a consumer needs.

Discharge:

The state of a mission_resource_access entry whose terminal_when completion condition has been met (Section 7). A discharged entry's authority is spent: it is no longer derivable.

Effective Authority Set:

The approved Authority Set after applying every issuer-held, monotonic narrowing mechanism the deployment runs. This profile contributes discharged entries (Section 7.3). Each other narrowing profile defines its own subtraction. No narrowing mechanism adds or restores authority. Membership in this set is necessary, never sufficient, for an action to proceed: the runtime decision evaluates it alongside every other required decision input ([I-D.draft-mcguinness-mission-runtime]).

All JSON shown in this document is non-normative and illustrative; the member definitions in the surrounding text are authoritative. HTTP message examples follow the conventions of [RFC9110]; long URLs and form parameters are wrapped for display. JWT and JWS examples are shown as decoded JSON with separate header objects; on the wire the JWS Compact Serialization [RFC7515] applies.

3. Mission Status Operation

This section is OPTIONAL. The issuance profile's stateless baseline needs no dedicated status surface ([I-D.draft-mcguinness-oauth-mission], Section "Mission Lifecycle and Gating"); a deployment that does not stand up this operation, and a consumer that does not use it, are unaffected.

The dedicated Mission Status operation is the canonical status surface the issuance profile defers. Unlike token introspection (Section 4), which answers "is this token's authorization still good," the Mission Status operation answers "what is the state of this Mission" keyed by the mission_id alone. Any consumer holding a mission_id (including an auditor or a cross-domain Resource AS) resolves it without holding a token the AS issued.

The Mission Issuer publishes its Mission Status endpoint URL in Authorization Server metadata (Section 9) as mission_status_endpoint, which a consumer resolves from a credential's mission.issuer. The endpoint MUST be served over TLS 1.2 or later (TLS 1.3 RECOMMENDED), following the recommendations of [RFC9325].

3.1. Request

The request is an HTTPS POST with an application/x-www-form-urlencoded body containing:

mission_id:

REQUIRED. A string. The canonical Mission Identifier, named per the issuance profile's external-surface convention ([I-D.draft-mcguinness-oauth-mission]).

audience:

CONDITIONAL. A string. The audience identifier of the requesting consumer. An authorized non-RS consumer (for example an auditor or a cross-domain Resource AS) that needs only Mission state, not audience-scoped authority, MAY omit audience; the response is then state-only and carries no authorization_details (Section 3.4). A Resource Server resolving authority for a specific audience MUST send it.

nonce:

REQUIRED. A string. A client-generated nonce binding the response to this request. It MUST be unique per request within the response lifetime. A consumer MUST reject a response whose nonce does not equal the one it sent. This is a standard client challenge: echoing it in the signed response anti-replay-binds that response to this specific request.

3.2. Authentication

The request MUST be authenticated. The AS MUST support at least one of the following mechanisms. The client MUST use exactly one of them per request:

  1. mTLS client authentication [RFC8705]. The AS validates the client's X.509 certificate against its configured trust anchors and the client's registered tls_client_auth metadata.

  2. Sender-constrained access token. The client presents a mission_status-scoped access token (see the authorization requirement below) in the Authorization header, sender-constrained either by DPoP [RFC9449] (the DPoP scheme with a DPoP proof header, the token's cnf.jkt matching the proof key thumbprint) or by mTLS [RFC8705] (a certificate-bound token, the Bearer scheme, whose cnf.x5t#S256 matches the presented client certificate). The token MUST be audience-restricted to this endpoint's protected-resource identifier (below).

  3. Private-key-JWT client authentication [RFC7523]. The client presents client_assertion_type with the exact value urn:ietf:params:oauth:client-assertion-type:jwt-bearer and a signed JWT as client_assertion. The assertion's aud MUST name the URL of the endpoint being invoked (the mission_status_endpoint for a Status request, the mission_lifecycle_endpoint for a Lifecycle request), not the token endpoint; the AS MUST reject an assertion whose aud names no such endpoint. The AS accepts only the JWS [RFC7515] algorithms it advertises for that endpoint (Section 9); none MUST NOT be used.

Plain Basic or POST client authentication MUST NOT be used for this endpoint. The AS MUST refuse a request not authenticated by one of the three mechanisms with unauthorized (HTTP 401). The mechanism is determined by wire evidence in order: a request presenting an access token in Authorization is mechanism 2, and any client certificate is then evaluated only as that token's mTLS sender constraint; otherwise a request presenting client_assertion is mechanism 3, and any client certificate is not treated as client authentication; otherwise a request presenting only a client certificate is mechanism 1. This order keeps "exactly one mechanism" satisfiable when mTLS terminates at the edge.

An authenticated caller MUST additionally carry an explicit read authorization: a mission_status scope on the presented access token, or a deployment-defined equivalent grant bound to the authenticated client. The mission_status scope authorizes the Mission Status read operation and mirrors the mission_lifecycle scope of the Mission Lifecycle endpoint (Section 6). The token-less path is preserved: a consumer that holds only a mission_id and authenticates directly as a client (mechanism 1 or 3) carries the deployment-defined equivalent grant, not a scope, and so resolves Mission state without holding an access token the AS issued. A caller carrying no such authorization is refused with the not-found response of Section 3.7 (Section 3.6).

A presented access token (mechanism 2) MUST be audience-restricted to this endpoint's protected-resource identifier: the resource value the AS publishes for this endpoint in its Protected Resource Metadata [RFC9728]. For these surfaces that identifier is the endpoint's own URL (the mission_status_endpoint or mission_lifecycle_endpoint), so the mechanism-2 access-token audience and the mechanism-3 private-key-JWT aud name the same value. The AS MUST reject a token whose audience does not name that identifier. This token audience is distinct from the request body's audience parameter (Section 3.1): the token audience authorizes the call at this endpoint, whereas the request audience carries no authentication weight and only selects the Resource-Server-specific authority projection the response returns (Section 3.4).

Which mechanisms and authorization this endpoint accepts are discoverable per endpoint, not inferred from the token endpoint's metadata. The AS advertises the methods this endpoint accepts in mission_status_endpoint_auth_methods_supported (Section 9). For the sender-constrained access-token path, this endpoint is an OAuth protected resource: the AS publishes, in its Protected Resource Metadata for this resource [RFC9728], the resource identifier the token's audience MUST name, the mission_status scope it requires (scopes_supported), and the presentation and sender constraints it accepts (bearer_methods_supported, dpop_bound_access_tokens_required, tls_client_certificate_bound_access_tokens). For the retained direct-client-authentication path (mTLS [RFC8705] or private-key JWT [RFC7523]), the accepted methods and, for private_key_jwt, the accepted client-assertion signing algorithms are advertised for this endpoint (Section 9), not read from the token endpoint's token_endpoint_auth_methods_supported [RFC8414]. Both paths are therefore discoverable.

3.3. Worked Request Example

POST /as/mission/status HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: DPoP eyJhbGciOiJFUzI1NiIsImtpZCI6...
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2Iiwi...

mission_id=msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-
&audience=https%3A%2F%2Ferp.example.com
&nonce=nonce_K9pV4nT2sR7mB1xQ

3.4. Response

On success the AS returns a JWS Compact Serialization [RFC7515] signed with a key published in the AS's jwks_uri. The JWS header carries typ of mission-status-response+jwt and a kid identifying the signing key. Per [RFC7515] Section 4.1.9 the typ header omits the application/ prefix; the full media type application/mission-status-response+jwt (registered in Section 13) is used as the HTTP Content-Type. Exact validation of the protected typ value, together with mutually exclusive validation rules for the artifact profiles, implements the substitution defense of [RFC8725], Sections 3.11 and 3.12.

[RFC9701] signed introspection responses are scoped to token introspection and do not apply to a lookup keyed by mission_id; the dedicated Mission Status operation therefore uses a new media type and a JWS, not [RFC9701] (see Section 11.4). Implementations MUST NOT use [RFC9701] for the dedicated Mission Status operation.

The signed payload reports the Mission's current state and the audience-scoped evidence the consumer needs.

HTTP/1.1 200 OK
Content-Type: application/mission-status-response+jwt
Cache-Control: no-store
Pragma: no-cache

eyJhbGciOiJFUzI1NiIsImtpZCI6InNhLWtleS0yMDI2LXEzIi...

Decoded JWS header:

{
  "alg": "ES256",
  "kid": "sa-key-2026-q3",
  "typ": "mission-status-response+jwt"
}

Decoded JWS payload:

{
  "iss": "https://as.example.com",
  "aud": "https://erp.example.com",
  "sub": "client_erp-recon-agent",
  "nonce": "nonce_K9pV4nT2sR7mB1xQ",
  "iat": 1793606400,
  "exp": 1793606460,
  "mission": {
    "id": "msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-",
    "issuer": "https://as.example.com",
    "authority_hash":
      "sha-256:l3KvZ4mP5x0wQrR6tY2nD9bM7sX1cF8gH2vJ4kE5pNQ",
    "state": "active",
    "version": 4,
    "expires_at":  "2026-12-31T23:59:59Z",
    "fresh_until": "2026-11-02T08:00:45Z"
  },
  "authorization_details": [
    { "type": "mission_resource_access",
      "resource": "https://erp.example.com",
      "actions": ["invoices.read", "journal-entries.write"] }
  ]
}

The members are:

  • The signed JWT envelope iss, aud, sub, nonce, iat, exp. The aud is the response's audience binding and the nonce its request binding. When the request omitted audience (Section 3.1), the response is state-only and the AS MUST set aud to the authenticated requester's identifier, as the Lifecycle endpoint does (Section 6); the consumer's aud verification below then checks that identifier. exp bounds the validity of the signed response itself; how long the consumer MAY rely on the reported state is given separately by mission.fresh_until below.

  • mission: the mission object, the same shape as the mission claim of [I-D.draft-mcguinness-oauth-mission] (Section "The Mission Claim") with status members added. It carries:

    • id, issuer: the subject Mission's identifier and issuer.

    • authority_hash: the issuance profile's consent commitment over the Authority Set ([I-D.draft-mcguinness-oauth-mission], Section "Integrity Anchors").

    • state: the current Mission lifecycle state. The authoritative state space is the issuance profile's ([I-D.draft-mcguinness-oauth-mission], Section "Mission Lifecycle and Gating"): the issuance profile states active, revoked, expired, this profile's suspended and completed when the Mission Lifecycle endpoint (Section 6) is deployed, and any further state a companion profile defines and the deployment runs (for example superseded, defined by the Mission Expansion profile ([I-D.draft-mcguinness-oauth-mission-expansion]) for an expanded predecessor, or cascaded, defined by the Mission Child Delegation profile ([I-D.draft-mcguinness-oauth-mission-child-delegation]) for a cascade-terminated Child Mission). A consumer applies the issuance profile's forward-compatibility rule: only active permits reliance, and every other value, recognized or not, is non-active. This profile's reliance behavior does not depend on recognizing these companion-defined states; the fail-safe rule above governs.

    • expires_at: the point at which the Mission itself expires, the Mission record's expires_at ([I-D.draft-mcguinness-oauth-mission]).

    • fresh_until: an RFC 3339 [RFC3339] date-time giving the point until which the consumer MAY rely on the reported state without re-checking, governing caching (Section 3.5). It is report-freshness metadata, carried in mission so it travels with state even on the introspection projection, which has no signed envelope to carry it (Section 4).

    • suspend_until, on_expiry: CONDITIONAL. Present only while the Mission is suspended under a deadline (Section 6): the RFC 3339 [RFC3339] deadline, and the transition (resume or revoke) the AS applies when it passes.

    • successor: OPTIONAL. A string, the successor mission_id. Present only when state is superseded, giving the successor that replaced this Mission, set atomically at supersession on the predecessor's record ([I-D.draft-mcguinness-oauth-mission-expansion]).

    • version: REQUIRED. The Mission's state version: a strictly monotonic per-Mission counter the Mission Issuer maintains, incremented on each committed lifecycle transition (the approval event is version 1) and each committed metadata-only change, current as of the reported state. It orders observations of one Mission across every surface: an event consumer that re-established state through this operation re-seats its gap detection on it (the last-applied Signals version becomes this value, [I-D.draft-mcguinness-oauth-mission-signals]), a lifecycle mutation can guard on it (Section 6.8), and a materialized policy view names the value it materialized ([I-D.draft-mcguinness-mission-runtime]).

    • status_list: OPTIONAL. The referenced-token status object of [I-D.draft-ietf-oauth-status-list] (idx and uri), present where the deployment publishes a Mission Status List (Section 5).

  • authorization_details: the audience-scoped Authority Set entries relevant to the requesting audience, as the mission_resource_access shape of [I-D.draft-mcguinness-oauth-mission] (Section "Mission Authority"), carried at the top level as a sibling of mission (as on the token and in the introspection response). Entries addressed to other audiences MUST NOT be disclosed. When the request omits audience (Section 3.1), there is no requesting audience: the response is state-only and MUST NOT carry authorization_details.

A consumer MUST verify, before honoring a response:

  1. the JWS header typ is mission-status-response+jwt;

  2. the JWS header alg is one the AS advertises in mission_status_signing_alg_values_supported (Section 9), rejecting none and any algorithm not listed;

  3. the JWS signature against a current jwks_uri entry for the issuer AS;

  4. iss equals the expected AS issuer URL;

  5. aud equals the consumer's own audience identifier;

  6. sub equals the requesting client's identifier;

  7. nonce equals the request's nonce;

  8. mission.id equals the requested mission_id; and

  9. iat is not in the future and exp is not in the past, with up to 30 seconds clock-skew tolerance.

3.5. Caching

Caching follows these rules:

  • Cache key. Consumers SHOULD cache a response keyed on (mission_id, audience), or on (mission_id, requester identifier) for a state-only response, until mission.fresh_until.

  • Hard stop. Consumers MUST NOT use a cached response after mission.fresh_until. In particular, a consumer MUST NOT extend reliance on a cached suspended (or any non-active) response beyond mission.fresh_until.

  • Freshness cap. When the AS advertises mission_max_stale_seconds (Section 9), it MUST NOT set mission.fresh_until later than the response iat plus that value.

  • Skew tolerance. When comparing the current time to mission.fresh_until, a consumer MAY allow up to 30 seconds of tolerance for the active state only, and no tolerance for any other state. The tolerance MUST NOT exceed the AS's advertised mission_max_stale_seconds (Section 9).

The freshness cap keeps report freshness within the deployment's advertised revocation-propagation tolerance. The skew tolerance is a clock-skew allowance on the reliance path, bounding the disagreement between the AS's and the consumer's clocks, not a property of state reversibility. The hard stop is absolute for non-active states because a suspended Mission may be resumed to active.

3.6. Anti-Oracle Property

A mission_id is never a bearer capability. The AS MUST authenticate the requester and authorize it for the requested mission_id and audience.

Unknown mission_id values and known-but-unauthorized references MUST produce indistinguishable responses (HTTP 404 with a generic not-found body; see Section 3.7). The AS MUST return an identical HTTP status code, response body, and headers for the two cases. The AS SHOULD NOT vary response timing in a way that distinguishes the two cases. It SHOULD mitigate timing side channels (for example by padding response time or by taking a uniform lookup path for both the unknown and the unauthorized case).

3.7. Error Responses

Mission Status outcomes are of two kinds. A success outcome is a found, visible, authorized Mission: the AS returns HTTP 200 with a signed Mission Status Response, and the outcome is described by mission.state in that response, not by a separate symbol. A wire error is a hard failure: the AS returns the matching HTTP status with a JSON object [RFC8259] body whose error member carries the symbol below.

Success outcomes (HTTP 200, signed Mission Status Response, described by mission.state):

Table 1
mission.state Description
active Mission is active and permits reliance.
suspended Mission is suspended (non-terminal).
revoked, expired, completed, superseded, cascaded Mission is in a terminal, non-active state.

This document uses "terminated" in prose for any terminal non-active state; it is not itself a mission.state value, and the terminal set is not closed. The terminal row above and the list that follows enumerate the companion-defined states this suite currently runs, for the reader's reference; a deployment reports whichever it runs, and a consumer's reliance decision never depends on recognizing them. The terminal states currently defined across this suite are revoked and expired ([I-D.draft-mcguinness-oauth-mission]), completed (this document), superseded ([I-D.draft-mcguinness-oauth-mission-expansion]), and cascaded ([I-D.draft-mcguinness-oauth-mission-child-delegation]). The binding rule is the issuance profile's forward-compatibility rule: every value other than active is non-active, whether or not the consumer recognizes it.

Wire error codes (carried in the error member of a JSON body):

Table 2
error HTTP Description
invalid_request 400 Malformed request: an unparseable body, a required member missing or malformed, an invalid member combination, or a retransmitted nonce paired with a request that is not byte-identical to the original (Section 6.8).
unauthorized 401 Request not authenticated.
not_found 404 Reference does not exist OR is not visible.
conflict 409 Lifecycle operation not legal from the current state (Section 6.8).
stale_version 409 expected_version differs from the current state version (Section 6.8).
rate_limited 429 Consumer is rate-limited.
unavailable 503 AS temporarily cannot serve status.

Note the distinction between the two access failures: unauthorized (401) means the request carried no valid authentication, whereas a request that is authenticated but not authorized for the referenced Mission returns not_found (404), never 401, so that an unauthorized reference is indistinguishable from an unknown one (Section 3.6). The error body is:

HTTP/1.1 404 Not Found
Content-Type: application/json
Cache-Control: no-store

{
  "error": "not_found",
  "error_description":
    "Mission reference is not found or not visible.",
  "nonce": "nonce_K9pV4nT2sR7mB1xQ"
}

The body MUST contain error and error_description, and MUST additionally contain nonce when the request carried a well-formed nonce. A request whose nonce is absent or malformed is refused invalid_request with no nonce member echoed. The body MUST NOT contain any member that would let a caller distinguish unknown from unauthorized references. For rate_limited, the response SHOULD include a Retry-After header [RFC9110] and a retry_after body member in seconds.

The OAuth-shaped surfaces of this family, this Status and Lifecycle endpoint, Mission Management [I-D.draft-mcguinness-oauth-mission-management], and the Mission Authority Server's submission surface [I-D.draft-mcguinness-mission-authority-server], share the error/error_description JSON body idiom for consistency with the OAuth-shaped APIs they compose with. Each surface's exact member requiredness is its own: here and in Mission Management, error_description and nonce are REQUIRED; the Mission Authority Server makes error_description OPTIONAL and adds the MAS-only error_reason. The body is application/json with Cache-Control: no-store. error_description is diagnostic and is never authorization input. nonce correlates the response to the request in support of the signed-response and retry model of Section 6.8 and is not, by itself, replay protection, per the absent-or-malformed-nonce rule above. RFC 9457 [RFC9457] problem details is neither used on these surfaces nor disparaged: the AuthZEN binding [I-D.draft-mcguinness-mission-authzen] carries it where that ecosystem does, and a future non-OAuth-shaped HTTP API in this family MAY choose it.

4. Token Introspection Mission Projection

This section is OPTIONAL and is a thin delta over the OAuth 2.0 Token Introspection [RFC7662] projection of [I-D.draft-mcguinness-oauth-mission] (Section "Mission State via Token Introspection"). That section already defines a mission member on the introspection response carrying id, issuer, authority_hash, and (from the Mission's issuer) the lifecycle state, together with the caller-authorization, minimization, and issuer-only-reports-state rules. This document does not restate those rules.

This extension adds the following to that projection:

This projection and the dedicated Mission Status Response (Section 3.4) carry Mission facts in a mission object of the same shape: the open mission claim object of [I-D.draft-mcguinness-oauth-mission] (Section "The Mission Claim") with status members (state, fresh_until, the status_list reference where the deployment publishes one (Section 5), and, on the dedicated response, expires_at and version) added. This projection populates the subset a token-holding consumer needs; the dedicated response populates more. Either way a consumer reads the same fact from the same place.

Example [RFC9701]-signed introspection response (decoded payload), for a token whose Mission is active:

{
  "iss": "https://as.example.com",
  "aud": "https://erp.example.com",
  "iat": 1793606400,
  "token_introspection": {
    "active":  true,
    "client_id": "s6BhdRkqt3",
    "sub":     "user_3p2q8mN1a0kV7tR",
    "scope":   "invoices.read",
    "mission": {
      "id": "msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-",
      "issuer": "https://as.example.com",
      "authority_hash":
        "sha-256:l3KvZ4mP5x0wQrR6tY2nD9bM7sX1cF8gH2vJ4kE5pNQ",
      "state":   "active",
      "fresh_until": "2026-11-02T08:00:45Z"
    }
  }
}

Per [RFC9701], the signed response is a JWT of typ token-introspection+jwt whose [RFC7662] members, including the mission projection, ride in the token_introspection claim; only iss, aud, and iat are top-level.

A consumer holding only a mission_id, or one that needs signed evidence independent of a specific token (an auditor or a cross-domain Resource AS), uses the dedicated Mission Status operation (Section 3); the introspection projection is purely a same-call convenience for token-holding consumers and is never the sole Mission Status path.

5. Mission Status List

One consumer often relies on many Missions at once: a gateway fronting an agent fleet holds a Mission per unit of work, and per-Mission status reads at that scale are a latency tax this profile's caching rules cannot amortize. A Mission Issuer MAY additionally publish Mission state as a Status List ([I-D.draft-ietf-oauth-status-list]): a signed, compressed bit array in which each participating Mission holds an index, fetched once per freshness window and read locally per action.

The arithmetic is the point. A fleet of 100,000 participating Missions at two bits per entry is 25,000 bytes before compression, and a mostly-active population compresses far below that; a consumer fetching that list once per 30-second window spends under a kilobyte per second to hold fresh state for every Mission it relies on, where per-Mission status reads would cost 100,000 requests per window. Fleet scale makes state freshness cheaper per Mission, not more expensive.

6. Mission Lifecycle Endpoint

This section is OPTIONAL. The issuance profile lets the Subject, Approver, or an administrator revoke a Mission by an authenticated, deployment-defined means and defers a standardized management API and the richer suspend, resume, and complete operations ([I-D.draft-mcguinness-oauth-mission], Section "Revocation"). This section standardizes that management surface.

The AS publishes its Mission Lifecycle endpoint URL in Authorization Server metadata (Section 9) as mission_lifecycle_endpoint, distinct from [RFC7009] token revocation. The endpoint MUST be served over TLS 1.2 or later (TLS 1.3 RECOMMENDED), following the recommendations of [RFC9325].

Adopting this endpoint extends the issuance profile's lifecycle state space ([I-D.draft-mcguinness-oauth-mission], Section "Mission Lifecycle and Gating") with two additional states: suspended (a non-terminal paused Mission that derives no tokens until resumed) and completed (a terminal state recording successful completion). Issuance gating treats any state other than active as non-deriving, exactly as the issuance profile gates on active.

A transition to suspended or completed gates new derivation only. Tokens already derived under the Mission remain valid until their own exp, exactly as in the issuance profile's revocation model and mirroring the treatment of superseded ([I-D.draft-mcguinness-oauth-mission-expansion]). A deployment that needs a prompt cutoff on outstanding tokens uses the propagation mechanisms of Section 8.

6.1. Operations

The endpoint accepts authenticated POST requests with a form-urlencoded body:

mission_id:

REQUIRED. A string. The canonical Mission Identifier, named per the issuance profile's external-surface convention ([I-D.draft-mcguinness-oauth-mission]).

operation:

REQUIRED. A string. One of revoke, suspend, resume, complete, discharge.

reason:

OPTIONAL. A string. A human-readable reason recorded in audit, maximum 1024 characters. Not used by discharge, which records its own request members in audit (Section 6.2).

suspend_until:

OPTIONAL. An RFC 3339 [RFC3339] date-time. Valid only on the suspend operation. When present, it sets a deadline after which the AS applies on_expiry.

on_expiry:

CONDITIONAL. A string, one of resume or revoke. REQUIRED when suspend_until is present; otherwise MUST NOT be sent. It selects the transition the AS applies when suspend_until passes.

nonce:

REQUIRED. A string. A client-generated nonce.

The discharge operation carries additional REQUIRED and OPTIONAL members of its own, defined in Section 6.2.

The operations are:

  • revoke: terminate the Mission; transition to revoked.

  • suspend: pause the Mission; transition to suspended.

  • resume: return a suspended Mission to active.

  • complete: mark the Mission completed; transition to completed.

  • discharge: commit that a terminal_when completion condition (Section 7.2) has fired, discharging a Mission-record entry. It changes no Mission-level state and is defined in its own subsection (Section 6.2).

A suspend MAY carry suspend_until with a REQUIRED on_expiry. When suspend_until passes, the AS MUST apply on_expiry (transition to active for resume, or to revoked for revoke) and emit the corresponding transition, without a further request. While the Mission is suspended under a deadline, both suspend_until and on_expiry surface in the signed Mission Status Response (Section 3.4) so a consumer sees the pending outcome.

6.2. Entry Discharge Operation

discharge commits that a terminal_when completion condition (Section 7.2) has fired, discharging the named Mission-record entry (Section 7.3). Beyond mission_id and nonce, it requires:

entry_digest:

REQUIRED. A string. The Authority Set entry commitment ([I-D.draft-mcguinness-oauth-mission]) of the mission_resource_access entry to discharge, computed over the immutable Mission-record entry, never over a narrowed token projection.

condition_digest:

REQUIRED. A string. The digest identifying the single terminal_when condition that fired, defined beside that member (Section 7.2).

event_type:

REQUIRED. A string. Echoed from the fired condition and cross-checked against the condition condition_digest names: a mismatch joins the not_found collapse, since distinguishing it would reveal information about a condition selected by digest (Section 6.2.2). event_type is never a selector by itself.

event_id:

REQUIRED. A string, 1*128( ALPHA / DIGIT / "-" / "_" / ":" / "." ) [RFC5234]. The identifier of the asserted external occurrence, used for evidence correlation and for the event-level deduplication of Section 6.2.3. It is distinct from nonce, the HTTP retry key of Section 6.8.

evidence_ref:

OPTIONAL. A URI, maximum 512 characters. A reference to evidence of the asserted occurrence.

evidence_digest:

OPTIONAL. A string, the family's prefixed digest form (sha-256: plus base64url, no-padding encoding), classified as a raw-octet digest ([I-D.draft-mcguinness-oauth-mission], Section "Commitment Mechanisms"): computed over the exact octets of the referenced artifact as exchanged, with no canonicalization. evidence_ref and evidence_digest MAY both appear: when they do, evidence_digest MUST commit the bytes evidence_ref names. Present alone, evidence_digest is independent audit metadata.

evidence_ref and evidence_digest are bounded audit metadata about the asserted occurrence. The AS MUST NOT dereference evidence_ref in baseline processing and MUST NOT treat either member as authorization input.

observed_at:

OPTIONAL. An RFC 3339 [RFC3339] date-time: a caller assertion. The AS validates it for syntax and reasonable clock bounds only, never as trusted ordering or freshness, and records its own commit time as received_at in audit.

Semantics:

  • Entry-level OR latch. The entry's terminal_when discharges on any condition being met (Section 7.2); the request names the condition that fired. The committed state is one monotonic latch on the entry, or on its selector equivalence class, one state-version increment, one audit record, and one notification. A later delivery presenting any valid condition against an already-discharged entry, a sibling condition, or the same condition under a different event_id, is acknowledged already_discharged (Section 6.2.4) and MUST NOT discharge the entry again or increment the version again; an exact event replay (the same tuple and the same fingerprint) is handled first by the dedup rule of Section 6.2.3. The latch MUST NOT revert, and issuance gating for a discharged entry is unchanged (Section 7.3).

  • Duplicate entries. One entry_digest discharges every recorded entry resolving to that digest as a single equivalence-class transition, and therefore one version increment, under the Authority Set entry commitment's selector equivalence-class rule ([I-D.draft-mcguinness-oauth-mission]).

  • States. discharge applies while the Mission is active or suspended: a suspended Mission still narrows monotonically. A delivery reaching the endpoint after completed, revoked, expired, or another terminal state returns an authenticated terminal_noop acknowledgement (Section 6.2.4) and MUST NOT create a transition or a version increment. discharge never changes Mission-level state; a deployment that also tracks all-entry completion invokes complete separately. The AS reaches this determination only after the selector and authorization validation of Section 6.2.2, so a terminal Mission is never a shortcut past those checks.

  • No expected_version. A stale-version refusal would delay a safety-reducing operation; the digest selectors above and the idempotency rules of Section 6.2.3 are the guards instead.

  • Atomicity. The entry latch (or its equivalence-class latch), the version increment, the audit and result record, and the durable propagation work (an outbox entry or a signal enqueue) commit as one unit. Where the deployment emits lifecycle events ([I-D.draft-mcguinness-oauth-mission-signals]), the signal enqueue is part of that same unit. Downstream materialization from the durable propagation work, including the child-delegation profile's entry-wise propagation to an already-justified Child Mission ([I-D.draft-mcguinness-oauth-mission-child-delegation]), is asynchronous and is not claimed atomic with this commit. Instead, a Child Mission's derivation MUST consult, or otherwise be gated by, the committed parent latch until that materialization completes, so no Child Mission can derive the discharged parent authority in the gap between the parent's commit and the child's materialized view.

6.2.1. Discharge Authority

Authorization for discharge requires a distinct mission_discharge scope or an equivalent deployment-defined grant. Possession of the mission_lifecycle scope (Section 6), or being the Mission's Subject, Approver, or an administrator, MUST NOT by itself imply discharge authority: a terminal_when condition is asserted by a resource or event authority, not by whoever may revoke, suspend, resume, or complete the Mission.

The baseline authority mapping is AS authorization policy keyed by event_type: the deployment publishes which authenticated principal (a client or workload identity, with its resource boundary where applicable) may assert each event type. Authentication uses the mechanism set of Section 3.2, sender-constrained where the deployment's profile requires it, and MUST bind the asserting principal.

A terminal_when condition MAY carry discharge_policy (OPTIONAL): a stable, opaque selector naming the AS-side authority mapping for that condition (Section 13.4). The AS MUST resolve and validate the selector whenever a condition first enters an immutable Mission-record entry: at Mission creation, and at every later point where a derived entry can carry a new condition (child creation, expansion, Token Exchange or other derivation, and any further profile that adds a condition), refusing the Intent or the derivation whose selector maps to nothing. The AS binds the resolved mapping's identifier and version to that exact condition_digest in issuer-held metadata. A requesting client MUST NOT select an arbitrary otherwise-valid policy merely because adding a condition is narrowing: an unchecked choice of mapping for a newly added condition could still force the premature discharge that Section 11.6 warns against, a denial-of-service on the task and an early retirement of its own guardrail. The member is never a raw principal or workload structure, and the requesting client cannot select an unapproved fallback.

6.2.2. Discharge Anti-Oracle

An unknown mission_id, an unknown entry_digest, an unknown condition_digest, an entry with no terminal_when, an event_type that does not match the condition condition_digest names, and a caller not authorized for that target all collapse to the endpoint's existing not_found treatment (Section 3.7). Authentication failure remains unauthorized (401). Detailed refusal reasons live only in issuer audit records.

The AS validates selector existence (mission_id, entry_digest, and condition_digest all resolve, the entry carries terminal_when, and event_type matches the named condition), then condition membership (the named condition belongs to the named entry), then target authorization (the discharge authority mapping of Section 6.2.1), before returning any terminal_noop acknowledgement (Section 6.2.4). This order keeps a terminal Mission from acting as a selector-existence oracle: every case the collapse above refuses is checked before a terminal Mission is ever distinguished from one whose selectors do not resolve.

6.2.3. Idempotency: nonce and event_id

discharge keeps two identities apart. nonce stays the HTTP operation retry key under Section 6.8's rules: a retransmission with the same nonce and a byte-identical request returns the stored signed response verbatim. The same nonce with a different request is refused invalid_request, never answered with an unrelated original response.

event_id deduplicates the external occurrence, scoped by (authenticated discharge authority, mission_id, entry_digest, condition_digest, event_id). A response's nonce MUST equal the one just sent (Section 3.4), so a retry that supplies a fresh nonce, as an at-least-once sender legitimately does, cannot receive the original signed response verbatim. Two cases follow:

  • Same nonce, same request. The stored signed response is returned verbatim, per the nonce rule above.

  • New nonce, same event tuple and the same assertion fingerprint (defined below). The AS performs no state-changing work: no re-latch, no version increment. It issues a new signed envelope that echoes the new nonce and carries the stored operation result: the same outcome and selectors, and the original prior_version and current_version the first commit produced.

Event assertion fingerprint. A semantic assertion object, never raw form bytes: the JSON object with exactly the decoded members operation (the literal string discharge), mission_id, entry_digest, condition_digest, event_type, event_id, and, when present, evidence_ref, evidence_digest, and observed_at. The object is canonicalized under the issuance profile's canonicalization ([I-D.draft-mcguinness-oauth-mission], Section "Canonicalization Rules") and digested as a canonical-object digest ([I-D.draft-mcguinness-oauth-mission], Section "Commitment Mechanisms"), since protocol context already fixes what the object commits. nonce, client authentication material, the DPoP proof, and transport headers are outside the fingerprint: none of them enter the assertion object, and none of them affect its value.

Over the (discharge authority, mission_id, entry_digest, condition_digest, event_id) tuple: the same tuple with the same fingerprint is the replay case above; the same tuple with a different fingerprint is refused conflict; the same event_id asserted against another Mission, entry, or condition is a valid, independent assertion, since one real-world event legitimately fans out to more than one target.

When both rules could apply, the nonce rule is evaluated first, since it governs the HTTP exchange; the event_id rule governs across distinct exchanges.

Retention. Event-dedup state MUST be retained at least as long as the deployment's published retry horizon and the replayable result's usable lifetime, and MAY be bounded by the Mission record's own retention. After eviction, a repeated assertion is processed fresh against the latch and yields already_discharged with no version increment, which is safe because the latch is monotonic.

6.2.4. Discharge Result

On success, discharge returns the endpoint's existing signed Mission Status Response envelope (Section 3.4), carrying a discharge_result object as a sibling of mission:

entry_digest, condition_digest, event_id:

the request's own selectors, echoed.

outcome:

one of discharged (this request committed the latch), already_discharged (a sibling condition, or the same condition under a different event_id, presented against an already-latched entry), or terminal_noop (the Mission was already in a terminal state). An exact event replay is handled first by the dedup rule (Section 6.2.3), never reaching this determination as a fresh already_discharged.

prior_version, current_version:

the Mission's state version immediately before and after the commit this result reports. For a request that itself commits, that commit is this request's own. For the new-nonce fresh-envelope case of Section 6.2.3, which commits nothing, these are the versions the original commit produced, unchanged. They are equal for already_discharged and terminal_noop.

With the echoed nonce, this is the durable acknowledgement an at-least-once sender stops retrying against.

6.4. Consolidated State Machine

This profile owns the extension of the issuance profile's lifecycle state space ([I-D.draft-mcguinness-oauth-mission], Section "Mission Lifecycle and Gating"). The table below is the authoritative view of that space: every state, every transition, and the source of the event that drives it. Event sources are the lifecycle endpoint (an operation of Section 6), the expiry clock (a deadline reached without a request), and companion adjudication (a transition a companion profile commits). The lifecycle-endpoint rows are exactly the Mission-state-changing operations of Section 6.3; discharge (Section 6.2) is a lifecycle-endpoint operation that changes no Mission state and so is not a row of this table. Only active permits derivation; every other state is non-deriving.

Table 4
From Event Event source To
(none) approval event issuance profile active
active revoke lifecycle endpoint revoked
suspended revoke lifecycle endpoint revoked
active suspend lifecycle endpoint suspended
suspended resume lifecycle endpoint active
active complete lifecycle endpoint completed
suspended complete lifecycle endpoint completed
active expires_at reached expiry clock expired
suspended expires_at reached expiry clock expired
suspended suspend_until reached, on_expiry = resume expiry clock active
suspended suspend_until reached, on_expiry = revoke expiry clock revoked
active successor activates expansion profile superseded
active parent reaches a terminal state child-delegation profile cascaded
suspended parent reaches a terminal state child-delegation profile cascaded

revoke and the Mission's expires_at both apply in suspended as well as active, so a suspended Mission can still be terminated or expire. The superseded and cascaded rows are companion-defined and shown here for reference: superseded is committed by the expansion profile and requires an active predecessor ([I-D.draft-mcguinness-oauth-mission-expansion]); cascaded is committed by the child-delegation profile only when a parent reaches a terminal state. A suspended parent holds a dependent Child Mission non-active reversibly rather than driving it to cascaded ([I-D.draft-mcguinness-oauth-mission-child-delegation]). Neither companion state is produced by this profile's endpoint.

6.5. Authentication

The lifecycle endpoint uses the same authentication mechanisms as the Mission Status endpoint (Section 3.2): mTLS client authentication, a sender-constrained access token (DPoP- or mTLS-bound), or private-key JWT. Its discovery mirrors that endpoint: the accepted methods in mission_lifecycle_endpoint_auth_methods_supported and, for private_key_jwt, the accepted client-assertion algorithms in mission_lifecycle_endpoint_auth_signing_alg_values_supported (Section 9). For the sender-constrained access-token path, this endpoint is an OAuth protected resource exactly as the Mission Status endpoint is: the AS publishes, in its Protected Resource Metadata for this resource [RFC9728], the resource identifier the token's audience MUST name and the scopes it requires (scopes_supported): mission_lifecycle for revoke, suspend, resume, and complete (Section 6), and, where the deployment offers discharge, mission_discharge as well (Section 6.2.1). A private-key JWT client_assertion MUST name the mission_lifecycle_endpoint URL in aud, and a presented access token MUST be audience-restricted to this endpoint's protected-resource identifier, exactly as at the Mission Status endpoint. Direct mTLS or private-key-JWT callers continue to use the deployment-defined equivalent grant, never a scope, exactly as discharge itself does (Section 6.2.1).

6.6. Authorization

This section governs revoke, suspend, resume, and complete; discharge has its own distinct authority model (Section 6.2.1), which a mission_lifecycle grant under this section MUST NOT imply.

The AS authorizes lifecycle operations against deployment policy. This document sets the minimum authorization semantics and leaves finer policy deployment-defined. Every authenticated caller, whatever its authentication mechanism (Section 3.2), MUST be governed by an explicit lifecycle authorization: a mission_lifecycle scope or a deployment-defined equivalent grant that names who may perform the transition. The AS MUST refuse a caller that carries no such authorization.

The acting party, and where the AS checks the lifecycle authorization, follow from the authentication case:

  1. When an access token authenticates the call, the token identifies the parties per the issuance profile's access-token model ([I-D.draft-mcguinness-oauth-mission]): for a delegated access token its sub denotes the resource owner (the represented party), matching the [RFC9068] access-token sub model; the calling party is identified by client_id ([RFC8693] Section 4.3); and, where a delegation chain is present, the immediate actor is identified by the act claim ([RFC8693], [I-D.draft-mcguinness-oauth-mission]). A DPoP [RFC9449] or mTLS [RFC8705] sender constraint binds the presenter to a key; it does not change what sub denotes. The acting party is the calling party so identified, and the presented token MUST carry the lifecycle authorization the AS checks against it.

  2. When the caller authenticates directly as a client (mTLS client authentication [RFC8705] or private-key JWT [RFC7523]), the authenticated client is the acting party. The AS MUST check the deployment-defined lifecycle grant bound to that client.

In every case the AS MUST record the acting party and SHOULD reflect it in the signed response's audit surface: the response envelope's sub, distinct from any access token's sub, or a deployment-defined audit member of the Mission Status Response.

Which parties may perform which operation is deployment-defined. Typical deployments authorize revoke to the Mission's Subject or Approver and to administrators; suspend and resume to administrators; and complete to the requesting client or an administrator.

Because resume returns a suspended Mission to active and so undoes the containment a suspend established, a deployment SHOULD require a distinct or elevated authorization for resume, mirroring the treatment of bulk resume in Mission Management ([I-D.draft-mcguinness-oauth-mission-management]).

The AS MUST refuse an unauthorized lifecycle request with the not-found response shape of Section 3.7, so the endpoint does not act as a Mission enumeration oracle.

6.7. Worked Examples

Revoke request:

POST /as/mission/lifecycle HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: DPoP eyJhbGciOiJFUzI1NiIsImtpZCI6...
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2Iiwi...

mission_id=msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-
&operation=revoke
&reason=Quarterly+reconcile+completed+early
&nonce=nonce_8Y3vN0sM6tP1xR9bQ5

Revoke success response: the AS returns the updated status as a signed Mission Status Response (Section 3.4). Because the Lifecycle request carries no audience, the response is state-only: the AS sets aud to the authenticated requester and omits authorization_details (a lifecycle confirmation reports state, not audience-scoped authority). Here the response envelope's sub, distinct from any access token's sub, carries the acting party: the calling client identified by client_id. The AS records that acting party and reflects it in this signed response as well as in its audit log.

HTTP/1.1 200 OK
Content-Type: application/mission-status-response+jwt
Cache-Control: no-store

eyJhbGciOiJFUzI1NiIsImtpZCI6InNhLWtleS0yMDI2LXEzIi...

Decoded JWS payload:

{
  "iss": "https://as.example.com",
  "aud": "client_erp-recon-agent",
  "sub": "client_erp-recon-agent",
  "nonce": "nonce_8Y3vN0sM6tP1xR9bQ5",
  "iat": 1793609600,
  "exp": 1793609660,
  "mission": {
    "id": "msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-",
    "issuer": "https://as.example.com",
    "authority_hash":
      "sha-256:l3KvZ4mP5x0wQrR6tY2nD9bM7sX1cF8gH2vJ4kE5pNQ",
    "state": "revoked",
    "version": 7,
    "expires_at":  "2026-12-31T23:59:59Z",
    "fresh_until": "2026-11-02T08:54:05Z"
  }
}

The AS records the operation, actor, time, and any reason in its audit log; the response confirms the outcome through the updated state.

Suspend request with a deadline, here also carrying the OPTIONAL expected_version guard against deciding over stale state (Section 6.8):

POST /as/mission/lifecycle HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: DPoP eyJhbGciOiJFUzI1NiIsImtpZCI6...
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2Iiwi...

mission_id=msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-
&operation=suspend
&suspend_until=2026-11-09T08%3A15%3A00Z
&on_expiry=revoke
&expected_version=5
&reason=Pending+quarterly+access+review
&nonce=nonce_4Dq2mV8kX1sB7nR3tW

Suspend success response: the signed Mission Status Response reports suspended and surfaces the pending outcome, carrying suspend_until and on_expiry in mission alongside state. Decoded JWS payload:

{
  "iss": "https://as.example.com",
  "aud": "client_erp-recon-agent",
  "sub": "client_erp-recon-agent",
  "nonce": "nonce_4Dq2mV8kX1sB7nR3tW",
  "iat": 1793607600,
  "exp": 1793607660,
  "mission": {
    "id": "msn_8RfX2Lqv9TqMv4z7sA2bN1k0YpEdHc9-",
    "issuer": "https://as.example.com",
    "authority_hash":
      "sha-256:l3KvZ4mP5x0wQrR6tY2nD9bM7sX1cF8gH2vJ4kE5pNQ",
    "state": "suspended",
    "version": 6,
    "suspend_until": "2026-11-09T08:15:00Z",
    "on_expiry": "revoke",
    "expires_at":  "2026-12-31T23:59:59Z",
    "fresh_until": "2026-11-02T08:20:45Z"
  }
}

When suspend_until passes without a resume, the AS applies on_expiry and transitions the Mission to revoked without a further request.

6.8. Idempotency and Conflicts

The request nonce (Section 6, Operations) is the idempotency key: an opaque string of 1 to 255 characters. The AS treats an absent, empty, longer, or non-string nonce as malformed (invalid_request, with no nonce echoed). The AS MUST deduplicate lifecycle requests by the triple (client, mission_id, nonce) for a bounded window. On a retransmit carrying a nonce already seen for that client and mission_id, together with a request byte-identical to the original, the AS MUST replay the original response rather than re-execute the operation. The same nonce paired with a request that is not byte-identical to the original MUST be refused invalid_request (Section 3.7); the AS MUST NOT answer it with the unrelated original response. The window MUST be at least the validity span of the signed response the AS would replay (its iat to exp, Section 3.4), so any retransmit that could still present a live response is deduplicated. A deployment MAY use a longer window. This makes a retransmit safe against reordering: a delayed suspend retry that arrives after a resume is recognized as a duplicate and replays the original suspend response, so it cannot re-suspend an already-resumed Mission.

Deduplication guards a retransmitted request; it does not guard a valid request decided over stale state, a fresh suspend issued from a console that has not yet seen a newer resume. For that a lifecycle request MAY carry expected_version, the state version (Section 3.4) the caller last observed: when present, the AS MUST refuse the operation with HTTP 409 and error symbol stale_version, leaving the Mission unchanged, when the Mission's current state version differs. A deployment SHOULD require expected_version on the operations it classifies high-risk. The nonce remains the replay key; the two guards are independent, one against duplicate delivery, one against stale decisions.

Lifecycle operations that change Mission state follow one rule. An operation whose resulting state (Section 6.3) equals the Mission's current state is idempotent success, terminal or not: the AS returns the current Mission Status Response, with no state change and no event emitted. Any other operation not legal from the current state (for example suspend against a terminal state) is a conflict: the AS MUST refuse it with HTTP 409 and a JSON body whose error symbol is conflict, leaving the Mission state unchanged. discharge changes no Mission state, so this rule does not bind it; its own idempotency and outcome vocabulary are defined in Section 6.2.3 and Section 6.2.4.

resume is the sole exception to the idempotent-success arm. It is legal only from suspended, and its resulting state active is also the baseline a Mission holds before any suspension, so resume on an active Mission (one never suspended, or already resumed) or on a terminal Mission is not idempotent success but a conflict.

One idempotent case carries metadata. A suspend against a suspended Mission whose suspend_until or on_expiry differ from the recorded values MUST update the recorded values, emitting the corresponding transition-metadata change and reporting the updated values in the response; silent acceptance without effect is not conforming.

6.9. Relationship to RFC 7009

A Mission revocation through this endpoint cascades to credentials derived from the Mission per the AS's advertised revocation propagation (Section 8). The AS MAY additionally invoke [RFC7009] token revocation for specific outstanding tokens when it knows their jti. [RFC7009] alone does NOT revoke a Mission; the lifecycle endpoint is the authoritative Mission state change.

6.10. Deferred Lifecycle Capabilities

This endpoint operates on one Mission at a time. Mission enumeration and bulk lifecycle operations for incident response, such as revoking every Mission for a compromised Subject, client, or tenant, are specified separately by Mission Management [I-D.draft-mcguinness-oauth-mission-management]; this document does not require them. The following capabilities remain deferred to future work. Approver transfer or re-anchoring, changing the party that anchors a Mission's consent, is not defined here. Administrative monotonic narrowing, such as shortening a Mission's expires_at, is not defined here.

7. Mission Completion and Entry Discharge

This section is OPTIONAL. A deployment that ends an entry's authority only by Mission revocation or expiry is fully conformant to the issuance profile and is unaffected by this section, which places no new requirement on the issuance profile: it defines one OPTIONAL entry member and the rules for handling it. A deployment claims the completion capability only when it issues or consumes entries carrying terminal_when. The capability is newer and less exercised than baseline issuance and runtime enforcement, and is not required by any Mission Assurance Level; its entry-discharge details may change.

The issuance profile gates issuance on Mission state but has no notion of an approved entry being done. A Mission granted authority to release a record "for this enrollment" keeps deriving that authority after the enrollment closes, until a clock or a revoke stops it. The Intent's success_criteria describe when the task is complete, but the issuance profile keeps them inert: they are rendered and committed, and carry no machine effect ([I-D.draft-mcguinness-oauth-mission]).

This section supplies the enforceable counterpart. It defines terminal_when, an OPTIONAL Common Constraint ([I-D.draft-mcguinness-oauth-mission]) on a mission_resource_access entry that carries one or more completion conditions. When a condition is met, the entry is discharged: the Authorization Server no longer derives a token carrying that entry (Section 7.3), exactly as it refuses derivation for a non-active Mission.

Three properties make this safe inside the Mission model and this section requires all three:

The threat analysis of these properties, including why a prompt-injected agent cannot use discharge to escalate and the forced-premature-discharge residual, is given in Section 11.6.

Discharge gates at the entry, not the Mission (Section 7.3). It strengthens the kill switch: a task that finishes stops issuing its own authority without waiting for a clock or a revoke.

7.1. Relationship to the Issuance Profile

The completion capability depends normatively on the issuance profile and is not implementable alone. It reuses, without restating, the issuance profile's Mission, mission_resource_access entry, Authority Set, subset rule, integrity anchors, lifecycle states, and issuance gating, and the inert success_criteria member of the Mission Intent. It uses Mission, Mission Issuer, Authority Set, and derivation as the issuance profile defines them.

It extends the issuance profile in one narrow, additive way: it registers terminal_when, an OPTIONAL Common Constraint on a mission_resource_access entry (Section 7.2), whose subset rule the issuance profile's existing subset comparison applies (Section 7.4). It changes no Mission lifecycle state and no meaning of any existing member.

7.2. Entry Completion Conditions

This section defines terminal_when, a Common Constraint ([I-D.draft-mcguinness-oauth-mission]) carried in the constraints object of a mission_resource_access entry. It is a specification-defined Common Constraint under the issuance profile's naming convention (Section 13).

terminal_when:

OPTIONAL. An array of one or more completion conditions. When any condition is met, the entry is discharged (Section 7.3). Each condition is an object with these members:

event_type:

REQUIRED. A string identifying the completion event. Its semantics are deployment- or registry-defined and opaque to this document, as purpose is ([I-D.draft-mcguinness-oauth-mission]).

discharge_policy:

OPTIONAL. A string, 1*64( ALPHA / DIGIT / "-" / "_" / ":" / "." ) [RFC5234], opaque. A stable selector naming the AS-side discharge-authority mapping for this condition (Section 6.2.1).

The terminal_when array is part of the entry's constraints and so of the Authority Set: it is committed by authority_hash and reproducible under derivation ([I-D.draft-mcguinness-oauth-mission]). Condition identity is byte equality of the condition object's canonical form under the issuance profile's canonicalization; an AS refuses a value carrying two identical conditions, and an intersection of two arrays deduplicates by that identity and sorts by the lexicographic order of the canonical bytes (Section 13.4), so the intersected entry is one reproducible array. Whether a condition has fired is evaluated state, not part of authority_hash; folding fired status into the anchor would make the committed authority time-varying.

condition_digest, used to select a condition on the discharge operation (Section 6.2), is a canonical-object digest ([I-D.draft-mcguinness-oauth-mission]) over the exact canonical bytes of the single condition object, in the issuance profile's encoded form: the same canonical form the registration's no-duplicate rule above already fixes as condition identity (Section 13.4).

terminal_when is the enforceable counterpart of the inert success_criteria ([I-D.draft-mcguinness-oauth-mission]), which remains inert: success_criteria describe completion for the Approver, terminal_when acts on it. It is distinct from a cumulative consumption bound, which meters volume; a terminal_when condition is a single external event.

7.3. Discharge and Issuance Gating

When a condition in an entry's terminal_when has been met, the entry is discharged. The Authorization Server MUST NOT derive a token carrying a discharged entry, at the token endpoint, on refresh, or on Token Exchange, exactly as issuance is refused for a non-active Mission ([I-D.draft-mcguinness-oauth-mission]). A derivation that would carry only discharged entries MUST fail. A derivation that carries a mix MUST omit the discharged entries.

Discharge gates at the entry, not the Mission. The Mission remains active and continues to derive its other entries: a multi-resource Mission therefore completes partially, one entry at a time, as each entry's task finishes. The issuance profile's Mission states are unchanged; a deployment that also tracks Mission-level completion MAY transition a Mission whose entries are all discharged to the completed state the Mission Lifecycle endpoint defines (Section 6), but this section does not require it. Such a transition is performed through the complete operation, as an issuer-initiated lifecycle operation, so the consolidated state machine's event sources remain authoritative (Section 6.4).

Discharge gates new derivations only. A token already issued for an entry remains valid until it expires, as with revocation ([I-D.draft-mcguinness-oauth-mission]). A deployment that needs prompt cutoff relies on short token lifetimes or on the runtime layer denying a discharged entry at the point of use (Section 7.7).

7.3.1. Determining Discharge

A discharge is committed one of two ways: through the discharge operation (Section 6.2), or by deployment-internal adjudication the issuer trusts, recorded under the same audited basis as any other lifecycle commit. This document defines no interoperable event-source polling profile of its own: the discharge operation is the interoperable path. An event-driven deployment wires its event bus to the lifecycle call. A deployment that determines completion by other means, such as a private status query or a recorded administrative action, invokes the same commit internally once it has decided.

Once committed, a discharge is recorded as Authorization-Server-side state and MUST NOT revert: a later delivery presenting any valid condition against an already-discharged entry is acknowledged already_discharged (Section 6.2.4) and does not restore the entry's authority.

A committed discharge is a committed metadata-only change for the purposes of the state version (Section 3.4): the Mission's state version increments at the commit, so a materialized policy view that commits a state version ([I-D.draft-mcguinness-mission-runtime]) is detectably obsolete after a discharge. Where Signals is deployed, the commit is carried by the generic authority_changed discriminator ([I-D.draft-mcguinness-oauth-mission-signals]); where Signals is not deployed, the version movement is what makes the change observable.

Before the AS receives and commits a discharge, it continues issuing against the entry. The posture this implies is stated plainly in Section 11.6.

7.3.2. Discharge Visibility

A discharged entry is no longer derivable, so the surfaces that report a Mission's authority MUST reflect that. Where the Mission Status operation (Section 3) and the token introspection projection (Section 4) are deployed, they MUST omit a discharged entry from the authorization_details they return. This is consistent with the audience filtering those surfaces already apply: a discharged entry, like an entry addressed to another audience, is not authority the caller may rely on.

Where Signals is deployed, a discharge commit rides the mission.lifecycle-change event's generic authority_changed discriminator [I-D.draft-mcguinness-oauth-mission-signals]: an active-to-active event carrying it signals that the Mission's effective authority narrowed even though state did not change.

7.4. Subset Rule

Because terminal_when is a Common Constraint, the issuance profile's subset comparison ([I-D.draft-mcguinness-oauth-mission]) applies its defined subset rule with no new clause: for a key present in the reference entry's constraints, the same key MUST be present in the candidate entry and its value MUST be no broader under the key's defined rule.

For terminal_when, a candidate value is no broader than a reference value when the candidate's condition array contains every condition of the reference, compared structurally after the canonicalization of the issuance profile ([I-D.draft-mcguinness-oauth-mission]); the candidate MAY add further conditions.

Conditions are compared structurally, not by event semantics. A child cannot drop or alter a parent's completion condition, only add more, so discharge composes monotonically: an added condition can only make an entry discharge sooner, which is a narrowing. Modifying a parent condition is forbidden because a verifier cannot decide whether the change discharges earlier or later from opaque event_type values.

7.5. Forward Compatibility

Because terminal_when is a constraints member, a consumer that does not recognize it fails closed by the issuance profile's Resource Server enforcement rule directly: a consumer MUST fail closed on any constraints key it does not understand, or understands but cannot enforce, refusing the request rather than granting access while ignoring the key ([I-D.draft-mcguinness-oauth-mission]). Discharge is load-bearing narrowing, so ignoring terminal_when would silently widen the grant. That enforcement rule is the honest basis of discharge's safety: an unrecognized terminal_when is refused, never dropped.

An Authorization Server that does not implement this capability simply does not emit terminal_when, and is unaffected. The fail-closed rule binds a consumer that encounters the constraint without implementing it.

7.6. Derivation Guidance

This guidance is non-normative. When the Authorization Server derives an entry from the Mission Intent, a reviewable rule governs what each element of the Intent becomes:

  • an action if removing it would leave the task undefined;

  • an ordinary constraints member if removing it would merely make the task less restrictive; and

  • a terminal_when completion condition, itself a constraints member, if it defines when the task is satisfied, retiring the entry's authority rather than widening or restricting it.

The third case is what this capability adds. A bound that holds throughout the task is an ordinary constraint; an event that ends the task is a terminal_when condition. For example, "only invoices under 500 USD" is a max_amount constraint, while "until the Q3 close is finalized" is a completion condition.

7.7. Relationship to Runtime Enforcement

Discharge is an issuance-gating signal and is fully meaningful at the issuance profile alone. It is also a natural input to the runtime layer ([I-D.draft-mcguinness-mission-runtime]): a runtime Policy Enforcement Point that recognizes terminal_when SHOULD deny a discharged entry at the point of use, closing the window between discharge and token expiry the same way it denies a revoked Mission. A Policy Enforcement Point learns that an entry is discharged from the Mission Status operation or the token introspection projection (Section 7.3.2), the same way it learns a Mission is revoked. A runtime Policy Enforcement Point that does not recognize terminal_when fails closed for the entry per Section 7.5.

For that point-of-use denial this document defines the denial-reason identifier authority_discharged, a family-coordinated name under the AuthZEN binding's denial-reason extension rule ([I-D.draft-mcguinness-mission-authzen]), carried wherever the runtime layer's denial reasons travel: the decision response's context.reason and the runtime evidence companion's denial_reason. It means the entry was approved and its completion condition fired, so the Mission Issuer discharged it: distinct from a containment denial (trust withdrawn) and from an out-of-authority denial (never approved). A consumer treats an unrecognized value as a deny under the binding's own rule; no other semantics attach.

7.8. Worked Example

A Mission for alice reconciles Q3 payables. Its Authority Set has two entries: a read over the ledger, and a write to post journal entries, bounded to under 500 USD and discharged when the Q3 close is finalized:

[
  { "type": "mission_resource_access",
    "resource": "https://erp.example.com",
    "actions": ["invoices.read"] },
  { "type": "mission_resource_access",
    "resource": "https://erp.example.com",
    "actions": ["journal-entries.write"],
    "constraints": {
      "max_amount": { "amount": "500.00", "currency": "USD" },
      "terminal_when": [
        { "event_type": "accounting-period-closed",
          "discharge_policy": "close-management-2026-q3" } ] } }
]

discharge_policy names the AS-side authority mapping approved for this condition: the close-management system's workload identity, not alice's agent, may assert accounting-period-closed (Section 6.2.1). The agent cannot drive its own discharge: it holds no mission_discharge authorization for that event_type.

While the period is open, the Authorization Server derives both entries. When the finance team finalizes the Q3 close, the close-management system calls discharge on the Mission Lifecycle endpoint, naming the write entry's entry_digest, this condition's condition_digest, event_type accounting-period-closed, and an event_id for its own occurrence record. The Authorization Server authenticates the caller against the resolved discharge_policy mapping, commits the latch, and returns a signed discharge_result of outcome discharged (Section 6.2.4). From then on the Authorization Server refuses to derive the write entry: a refresh returns a token carrying only the read entry. The Mission stays active, so the agent can still read the ledger to finish its reconciliation report, but it can no longer post journal entries. No revoke and no clock was needed; the write authority retired itself when the task it was granted for completed.

7.9. Completion Conformance

An Authorization Server claiming the completion capability MUST:

  • treat an entry whose terminal_when has been discharged as discharged and refuse to derive it (Section 7.3);

  • commit a discharge only through the discharge operation, meeting its authority, anti-oracle, idempotency, and atomicity requirements (Section 6.2), or through an equivalently audited deployment-internal adjudication (Section 7.3.1);

  • record a committed discharge as latched state that MUST NOT revert (Section 7.3.1);

  • carry every parent completion condition into a derived entry when narrowing, permitting only added conditions (Section 7.4);

  • where it offers the Mission Status operation or the token introspection projection, omit a discharged entry from the authorization_details it returns (Section 7.3.2); and

  • keep the terminal_when condition array committed by authority_hash and keep fired status out of it (Section 7.2).

A consumer claiming the completion capability MUST fail closed for an entry carrying a terminal_when constraint it does not understand (Section 7.5).

8. Revocation Propagation

This section is OPTIONAL. The issuance profile bounds outstanding self-contained tokens by their lifetime and OPTIONAL token introspection ([I-D.draft-mcguinness-oauth-mission], Section "Revocation"). A deployment that needs a Mission state change to take effect faster than token lifetime alone combines the propagation mechanisms this suite offers and sizes token lifetimes to match.

The mechanisms are each discovered from their own metadata, not from a separate posture list:

A deployment advertises mission_max_stale_seconds (Section 9), the maximum interval it tolerates for a Mission state change to take effect, so a consumer can size token lifetimes and choose propagation mechanisms to match. When the member is absent, no propagation bound is declared: a consumer MUST size reliance to token lifetime alone and MUST NOT assume a tighter bound.

Where the member is present, a status response's mission.fresh_until MUST NOT exceed the response's issuance time plus the advertised bound: the advertisement is the ceiling on every reliance window built from these surfaces, including a runtime permit's validity window, which is capped by the state view's freshness. As sizing guidance, the runtime enforcement profile's recommended defaults target an effective bound under 300 seconds for the high-consequence classes; the 60-second value in this document's examples is a tight deployment's choice, not a floor.

9. Authorization Server Metadata

This section is OPTIONAL and applies only to a deployment that adopts one or more of the extensions above. An AS advertises the surfaces it supports through the following members of its Authorization Server metadata document [RFC8414], in addition to the issuance profile's mission_bound_authorization_supported ([I-D.draft-mcguinness-oauth-mission], Section "Authorization Server Metadata"). Unlike the issuance profile, which advertises only that boolean, this document defines OAuth AS metadata members for the endpoints and classes it introduces, so a consumer discovers them through standard [RFC8414] discovery.

mission_status_endpoint:

OPTIONAL. A string containing a URL. The URL of the dedicated Mission Status operation (Section 3). Present when the AS supports it.

mission_status_endpoint_auth_methods_supported:

OPTIONAL. A JSON array of strings naming the authentication methods the Mission Status endpoint (Section 3) accepts. Its value space is a closed set defined by this document, not the OAuth Token Endpoint Authentication Methods registry: mtls_client_auth (mutual-TLS client authentication [RFC8705]), private_key_jwt (private-key JWT client authentication [RFC7523]), and access_token (a mission_status-scoped, sender-constrained access token, whose presentation and DPoP or mTLS binding are described by this endpoint's Protected Resource Metadata [RFC9728]). The first two values are spelled identically to registered token-endpoint authentication methods by intent; this member describes this endpoint, not the token endpoint. Present, and SHOULD be advertised, when the AS serves the Mission Status endpoint.

mission_status_endpoint_auth_signing_alg_values_supported:

OPTIONAL. A JSON array of strings, the JWS [RFC7515] algorithm values the AS accepts for the private_key_jwt client-assertion JWT (Section 3.2) at the Mission Status endpoint. This is the client-assertion verification set, not the response-signing algorithms of mission_status_signing_alg_values_supported below. none MUST NOT be used. Present when that endpoint lists private_key_jwt.

mission_status_signing_alg_values_supported:

OPTIONAL. A JSON array of strings. The JWS [RFC7515] algorithm values the AS uses to sign the Mission Status Response shape (Section 3.4), on whichever surfaces of this profile family serve it (the dedicated Mission Status operation, the Lifecycle endpoint, and Mission Management), mirroring introspection_signing_alg_values_supported. These are the response-signing algorithms, not the algorithms the AS accepts on private_key_jwt client assertions (the endpoint auth-signing members). Present when the AS serves any such surface.

mission_lifecycle_endpoint:

OPTIONAL. A string containing a URL. The URL of the Mission Lifecycle endpoint (Section 6). Present when the AS supports it.

mission_lifecycle_endpoint_auth_methods_supported:

OPTIONAL. A JSON array of strings naming the authentication methods the Mission Lifecycle endpoint (Section 6) accepts, from the same closed value space as mission_status_endpoint_auth_methods_supported (with access_token naming a mission_lifecycle-scoped access token). Present, and SHOULD be advertised, when the AS serves the Mission Lifecycle endpoint.

mission_lifecycle_endpoint_auth_signing_alg_values_supported:

OPTIONAL. A JSON array of strings, the JWS [RFC7515] algorithm values the AS accepts for the private_key_jwt client-assertion JWT (Section 3.2) at the Mission Lifecycle endpoint. This is the client-assertion verification set, not the response-signing algorithms of mission_status_signing_alg_values_supported. none MUST NOT be used. Present when that endpoint lists private_key_jwt.

mission_max_stale_seconds:

OPTIONAL. An integer. The maximum tolerated interval, in seconds, for revocation propagation (Section 8). When absent, no bound is declared, and a consumer sizes reliance to token lifetime alone.

DPoP and mTLS support for issued credentials are read from the standard dpop_signing_alg_values_supported [RFC9449] and tls_client_certificate_bound_access_tokens [RFC8705] metadata; this document defines no separate sender-constraint member. When the introspection projection (Section 4) is signed, the signing is discovered through the standard introspection_signing_alg_values_supported metadata.

9.1. Worked Metadata Example

A discovery response from https://as.example.com/.well-known/oauth-authorization-server, showing the issuance profile members plus the extension members of this document:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=3600

{
  "issuer": "https://as.example.com",
  "token_endpoint": "https://as.example.com/as/token",
  "introspection_endpoint":
    "https://as.example.com/as/introspect",
  "jwks_uri":
    "https://as.example.com/.well-known/jwks.json",
  "introspection_signing_alg_values_supported": ["ES256"],
  "mission_bound_authorization_supported": true,

  "mission_status_endpoint":
    "https://as.example.com/as/mission/status",
  "mission_status_endpoint_auth_methods_supported":
    ["mtls_client_auth", "private_key_jwt", "access_token"],
  "mission_status_endpoint_auth_signing_alg_values_supported": ["ES256"],
  "mission_status_signing_alg_values_supported": ["ES256"],
  "mission_lifecycle_endpoint":
    "https://as.example.com/as/mission/lifecycle",
  "mission_lifecycle_endpoint_auth_methods_supported":
    ["mtls_client_auth", "private_key_jwt", "access_token"],
  "mission_lifecycle_endpoint_auth_signing_alg_values_supported": ["ES256"],
  "mission_max_stale_seconds": 60
}

10. Conformance

An implementation conforms to the issuance profile [I-D.draft-mcguinness-oauth-mission] or implements the Mission Issuer role of a binding that serves these surfaces, such as the standalone Mission Authority Server [I-D.draft-mcguinness-mission-authority-server]. Each extension in this document is independently OPTIONAL; an implementation names the ones it supports (for example, "issuance profile with Mission Status and Mission Lifecycle"), and an implementation that supports none of them is still a conforming issuance profile.

An implementation claiming an extension MUST meet its requirements:

An implementation meets the following requirement independent of which extensions above it claims. Every issuer-held narrowing mechanism a deployment runs, this profile's discharge or a companion profile's own overlay alike, MUST feed the single Effective Authority Set computation. Every derivation and every authority-reporting surface MUST use that same computation; no mechanism computes a parallel view, and no surface reports authority the computation has not reduced.

11. Security Considerations

The security considerations of the issuance profile [I-D.draft-mcguinness-oauth-mission] apply in full. This section covers threats specific to the extensions defined here.

11.1. Mission Status Enumeration

Per the anti-oracle property (Section 3.6), the AS MUST NOT let a caller readily distinguish an unknown mission_id from a known-but-unauthorized one at the Status or Lifecycle endpoint. The error shape of Section 3.7 requires identical body content, identical HTTP status, and identical headers between the two cases, and the AS SHOULD additionally suppress timing side channels (for example by padding response time or by taking a uniform lookup path). An implementation that leaks the distinction exposes the Mission space to enumeration.

11.2. Mission Status Response Replay

A Mission Status Response is bound to (caller sub, audience, nonce, issuance time). Replay against a different caller or audience, or beyond mission.fresh_until, is detectable by signature verification and by verifying the bindings; a consumer MUST verify all the checks of Section 3.4 before honoring a response. A response cached and replayed by the same caller within mission.fresh_until is equivalent to a fresh response; a consumer MUST NOT use a cached response after mission.fresh_until, with the skew tolerance of Section 3.5.

11.3. Mission Status Denial of Service

The Mission Status operation is on the consumption path of every Mission-bound credential validation in deployments where consumers query Mission Status per request. The AS MUST implement per-consumer rate limiting (returning rate_limited, Section 3.7) and SHOULD encourage consumer-side caching (Section 3.5) to reduce traffic.

11.4. RFC 9701 vs. New Media Type

When the introspection projection is signed (Section 4), it uses [RFC9701], which is scoped to token introspection. The dedicated Mission Status operation uses a new media type (application/mission-status-response+jwt, Section 13) and a JWS [RFC7515], because [RFC9701] does not apply to a lookup keyed by mission_id. Implementations MUST NOT use [RFC9701] for the dedicated Mission Status operation, and MUST NOT accept an unsigned response from the dedicated Mission Status operation in place of the signed form it requires.

11.5. Signing-Key Retention for Audit

The AS signs Mission Status and Lifecycle responses with a key from its jwks_uri. The AS MUST keep the public JWK for every kid it has signed such a response under resolvable in its jwks_uri for at least the Mission record retention period, so an archived application/mission-status-response+jwt remains verifiable for audit and dispute. This is the issuance profile's retired-key rule ([I-D.draft-mcguinness-oauth-mission]), with the record retention period as the bound. A key known or suspected compromised is the exception: the AS removes it, and the Mandate profile's compromise-time rule governs how artifacts signed under it are then classified.

11.6. Entry Discharge

The completion capability (Section 7) adds the following:

  • Monotonic by construction. Discharge only removes an entry's authority, so it is not a path to escalation; a compromised or injected agent cannot use terminal_when to widen authority, and the worst it can do is retire its own authority sooner. That is not an escalation, but a forced premature discharge is a denial-of-service on the task (authority the task still needs is withdrawn) and, where discharge is relied on as a guardrail, retires that guardrail early. Discharge authority (Section 6.2.1) bounds who can force it.

  • Fail closed on unknown constraint. A consumer that does not understand the terminal_when constraint MUST refuse the entry (Section 7.5); ignoring the constraint would let a discharged entry continue to be narrowed, projected, or enforced, defeating discharge.

  • Notification delivery is a temporary widening, not a fail-closed property. Before the AS receives and commits a discharge, it continues issuing against the entry: a lost or suppressed notification is a temporary widening relative to the real-world event, bounded by authenticated at-least-once delivery with retries to an idempotent acknowledgement (Section 6.2.4), monitoring and reconciliation, and the Mission's and its tokens' own lifetimes. This is not a fail-closed property: a deployment requiring cannot-determine-means-no-issuance runs a synchronous status or policy check outside this baseline.

  • RS enforcement honesty. A stateless Resource Server cannot evaluate issuer-held discharge state from the token alone; it honors the issued token until expiry. Prompt cutoff on a discharged entry requires status (Section 3), introspection (Section 4), or runtime enforcement (Section 7.7); an entry constraint the enforcing party does not understand still fails closed (Section 7.5).

  • Already-issued tokens. The window between discharge and the expiry of a token already issued is the same residual revocation carries, bounded the same way (Section 7.3, Section 7.7).

11.7. General OAuth Security

This document inherits OAuth 2.0 Best Current Practice [RFC9700] for the OAuth surfaces it composes with; implementers MUST follow current OAuth security guidance.

12. Privacy Considerations

The privacy considerations of the issuance profile [I-D.draft-mcguinness-oauth-mission] apply in full. This section covers privacy specific to the extensions here.

12.1. Status and Lifecycle as Disclosure Surfaces

The Mission Status operation (Section 3) and the introspection projection (Section 4) disclose Mission state, the authority_hash, and the audience-scoped authorization_details to the authenticated, authorized requester. A deployment MUST treat both as Mission information-disclosure surfaces with the same privacy posture, audience-filtering the disclosed authority so a consumer never sees entries addressed to other audiences (Section 3.4).

12.2. Status Audit Logging

The AS records Status and Lifecycle requests (containing mission_id, audience, caller, and timing) in audit logs. Deployments MUST treat these logs as PII sinks per the issuance profile's privacy considerations.

12.3. Completion Condition Disclosure

A terminal_when condition can reveal task structure: event_type may name a business event, a case, or a record whose mere existence is sensitive, and it rides the token where the entry is carried. A deployment SHOULD treat it as it treats other authority detail, and SHOULD avoid event identifiers that disclose more than the consuming party needs. discharge_policy is an opaque selector and does not itself name a business event, but its resolution is deployment-defined and MAY correlate with a class of sensitive events; a deployment SHOULD weigh that when publishing its meaning. The event_id, evidence_ref, evidence_digest, and observed_at a discharge request carries (Section 6.2) do not ride the token; they land only in issuer audit records, which deployments MUST treat as Mission information-disclosure surfaces per the audit-logging rule above.

13. IANA Considerations

This document requests IANA actions for OAuth AS metadata members, a media type, and a registration in the issuance profile's Mission Common Constraints registry. It defines no new registry of its own: the endpoint authentication-method value space is a closed set defined inline (Section 9), and the terminal_when Common Constraint is registered in the issuance profile's registry ([I-D.draft-mcguinness-oauth-mission]), not established as a registry here (Section 13.4).

13.1. OAuth Authorization Server Metadata Registration

IANA is requested to register the following in the "OAuth Authorization Server Metadata" registry [RFC8414]. For each: Change Controller IETF; Reference this document, Section 9.

  • mission_status_endpoint

  • mission_status_endpoint_auth_methods_supported

  • mission_status_endpoint_auth_signing_alg_values_supported

  • mission_status_signing_alg_values_supported

  • mission_lifecycle_endpoint

  • mission_lifecycle_endpoint_auth_methods_supported

  • mission_lifecycle_endpoint_auth_signing_alg_values_supported

  • mission_max_stale_seconds

13.2. Media Type Registration

IANA is requested to register one media type per [RFC6838].

13.2.1. application/mission-status-response+jwt

  • Type name: application

  • Subtype name: mission-status-response+jwt

  • Required parameters: none

  • Optional parameters: none

  • Encoding considerations: binary; JWS Compact Serialization

  • Security considerations: see Section 11

  • Interoperability considerations: see this document

  • Published specification: this document

  • Applications that use this media type: OAuth Mission-Bound consumers

  • Fragment identifier considerations: not applicable

  • Restrictions on usage: none

  • Provisional registration: no

  • Magic number(s): none

  • File extension(s): none

  • Macintosh file type code(s): none

  • Person & email address to contact: Karl McGuinness public@karlmcguinness.com

  • Intended usage: COMMON

  • Author/Change controller: IETF

13.3. Mission Lifecycle States Registrations

This document requests registration of two states in the issuance profile's Mission Lifecycle States registry ([I-D.draft-mcguinness-oauth-mission]), under that registry's Specification Required policy:

Table 5
Value Terminal Semantics Change Controller Reference
suspended no A paused Mission that derives no tokens until resumed. IETF this document, Section 6
completed yes Records successful completion of the Mission. IETF this document, Section 6

13.4. Common Constraints Registry: terminal_when

The completion capability (Section 7) registers one Common Constraint in the issuance profile's Mission Common Constraints registry ([I-D.draft-mcguinness-oauth-mission]), under that registry's Specification Required policy. This document supplies the registration's required fields:

  • Key Name: terminal_when

  • Value Space: a JSON array of one or more completion-condition objects, each with a REQUIRED event_type (string) and an OPTIONAL discharge_policy (string, an opaque selector); no two conditions in one array share a canonical form (Section 7.2). This Value Space is a breaking change, while this experimental draft's registration is still open, to the one a prior revision registered: event_source and max_staleness are removed and discharge_policy is added.

  • Subset Rule: a candidate value is no broader than a reference value when the candidate's condition array contains every condition of the reference, compared structurally after the issuance profile's canonicalization; the candidate MAY add further conditions (Section 7.4).

  • Intersection Rule: the union of the two condition arrays, where condition identity is byte equality of each condition object's canonical form under the issuance profile's canonicalization ([I-D.draft-mcguinness-oauth-mission]): byte-identical conditions collapse to one, and the union is sorted by the lexicographic order of those canonical bytes, so two implementations produce the identical array and the identical authority_hash.

  • Change Controller: IETF

  • Reference: this document, Section 7.2

terminal_when is a constraints member of the mission_resource_access authorization details type defined by the issuance profile ([I-D.draft-mcguinness-oauth-mission]). event_type values are deployment- or registry-defined and opaque to this document, as purpose is, so this document establishes no registry of event types.

13.5. Well-Known URI

This document registers no new Well-Known URI. The metadata members of Section 9 are added to the OAuth Authorization Server Metadata document at /.well-known/oauth-authorization-server [RFC8414].

Acknowledgments

The author thanks the implementers and reviewers of the Mission-Bound Authorization work for feedback that shaped these extensions.

References

Normative References

[I-D.draft-ietf-oauth-status-list]
Looker, T., Bastian, P., and C. Bormann, "Token Status List (TSL)", Work in Progress, Internet-Draft, draft-ietf-oauth-status-list-21, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-status-list-21>.
[I-D.draft-mcguinness-oauth-mission]
McGuinness, K., "Mission-Bound Authorization for OAuth 2.0", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission.html>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC3339]
Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/rfc/rfc3339>.
[RFC5234]
Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, , <https://www.rfc-editor.org/rfc/rfc5234>.
[RFC6838]
Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, , <https://www.rfc-editor.org/rfc/rfc6838>.
[RFC7009]
Lodderstedt, T., Ed., Dronia, S., and M. Scurtescu, "OAuth 2.0 Token Revocation", RFC 7009, DOI 10.17487/RFC7009, , <https://www.rfc-editor.org/rfc/rfc7009>.
[RFC7515]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, , <https://www.rfc-editor.org/rfc/rfc7515>.
[RFC7523]
Jones, M., Campbell, B., and C. Mortimore, "JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants", RFC 7523, DOI 10.17487/RFC7523, , <https://www.rfc-editor.org/rfc/rfc7523>.
[RFC7662]
Richer, J., Ed., "OAuth 2.0 Token Introspection", RFC 7662, DOI 10.17487/RFC7662, , <https://www.rfc-editor.org/rfc/rfc7662>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8259]
Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/rfc/rfc8259>.
[RFC8414]
Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 Authorization Server Metadata", RFC 8414, DOI 10.17487/RFC8414, , <https://www.rfc-editor.org/rfc/rfc8414>.
[RFC8693]
Jones, M., Nadalin, A., Campbell, B., Ed., Bradley, J., and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693, DOI 10.17487/RFC8693, , <https://www.rfc-editor.org/rfc/rfc8693>.
[RFC8705]
Campbell, B., Bradley, J., Sakimura, N., and T. Lodderstedt, "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", RFC 8705, DOI 10.17487/RFC8705, , <https://www.rfc-editor.org/rfc/rfc8705>.
[RFC9068]
Bertocci, V., "JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens", RFC 9068, DOI 10.17487/RFC9068, , <https://www.rfc-editor.org/rfc/rfc9068>.
[RFC9325]
Sheffer, Y., Saint-Andre, P., and T. Fossati, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)", BCP 195, RFC 9325, DOI 10.17487/RFC9325, , <https://www.rfc-editor.org/rfc/rfc9325>.
[RFC9449]
Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449, , <https://www.rfc-editor.org/rfc/rfc9449>.
[RFC9701]
Lodderstedt, T., Ed. and V. Dzhuvinov, "JSON Web Token (JWT) Response for OAuth Token Introspection", RFC 9701, DOI 10.17487/RFC9701, , <https://www.rfc-editor.org/rfc/rfc9701>.
[RFC9728]
Jones, M.B., Hunt, P., and A. Parecki, "OAuth 2.0 Protected Resource Metadata", RFC 9728, DOI 10.17487/RFC9728, , <https://www.rfc-editor.org/rfc/rfc9728>.

Informative References

[I-D.draft-mcguinness-mission-aauth]
McGuinness, K., "Mission Context Binding for AAuth", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-mission-aauth.html>.
[I-D.draft-mcguinness-mission-authority-server]
McGuinness, K., "Mission Authority Server", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-mission-authority-server.html>.
[I-D.draft-mcguinness-mission-authzen]
McGuinness, K., "Mission-Bound Runtime Enforcement: AuthZEN Profile", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-mission-authzen.html>.
[I-D.draft-mcguinness-mission-mandate]
McGuinness, K., "Mission Mandate", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-mission-mandate.html>.
[I-D.draft-mcguinness-mission-runtime]
McGuinness, K., "Mission-Bound Runtime Enforcement", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-mission-runtime.html>.
[I-D.draft-mcguinness-oauth-mission-child-delegation]
McGuinness, K., "Mission Child Delegation for OAuth 2.0", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission-child-delegation.html>.
[I-D.draft-mcguinness-oauth-mission-cross-domain]
McGuinness, K., "Mission Cross-Domain Projection for OAuth 2.0", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission-cross-domain.html>.
[I-D.draft-mcguinness-oauth-mission-expansion]
McGuinness, K., "Mission Expansion for OAuth 2.0", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission-expansion.html>.
[I-D.draft-mcguinness-oauth-mission-management]
McGuinness, K., "Mission Management for OAuth 2.0", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission-management.html>.
[I-D.draft-mcguinness-oauth-mission-signals]
McGuinness, K., "Mission Lifecycle Signals for OAuth 2.0", , <https://mcguinness.github.io/mission-bound-authorization/draft-mcguinness-oauth-mission-signals.html>.
[RFC8725]
Sheffer, Y., Hardt, D., and M. Jones, "JSON Web Token Best Current Practices", BCP 225, RFC 8725, DOI 10.17487/RFC8725, , <https://www.rfc-editor.org/rfc/rfc8725>.
[RFC9110]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/rfc/rfc9110>.
[RFC9457]
Nottingham, M., Wilde, E., and S. Dalal, "Problem Details for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, , <https://www.rfc-editor.org/rfc/rfc9457>.
[RFC9700]
Lodderstedt, T., Bradley, J., Labunets, A., and D. Fett, "Best Current Practice for OAuth 2.0 Security", BCP 240, RFC 9700, DOI 10.17487/RFC9700, , <https://www.rfc-editor.org/rfc/rfc9700>.

Author's Address

Karl McGuinness
Independent