---
title: "Mission Lifecycle and Change"
date: "2026-06-06T16:00:00-07:00"
lastmod: "2026-06-06T16:00:00-07:00"
description: "A Mission is not static. This part makes its state a first-class, fail-safe surface. A consumer holding only a mission_id can observe current state and be told when it changes, an authorized party can revoke or suspend it, growth happens only through a fresh approval that supersedes its predecessor, and authority retires itself one entry at a time as work finishes."
summary: "The issuance core gives a Mission three states and gates derivation on active. This part adds the surfaces that make state actionable over time: Status for canonical pull freshness with Signals as its experimental push complement, Expansion for governed growth, and Completion for monotonic narrowing. One rule threads through all four. Only active permits reliance, so every state a newer profile adds fails safe for a consumer that predates it."
slug: "mission-lifecycle-and-change"
tags:
  - "OAuth"
  - "Authorization"
  - "Agentic Identity"
  - "Mission-Bound Authorization"
  - "Intent-Based Authorization"
  - "AuthZEN"
  - "Internet-Draft"
series:
  - "building-mission-bound-authorization"
---


{{< spine steps="mission" >}}

{{< tldr >}}

- **The argument.** A Mission is approved once but lives for the duration of a task. Approval is a moment. The task is a span. If the only way a consumer learns a Mission's current state is the lifetime of a token it already holds, then a revoked Mission keeps deriving authority until tokens age out. This part makes Mission state a *first-class, fail-safe surface* that consumers observe, parties change, and that grows and shrinks under governance.
- **What lives in this post.** Four verbs over one object: [observe and revoke](#observe-and-revoke-pull-and-push) (Status as the canonical pull surface, Signals as its experimental push complement), [grow](#grow-expansion-creates-a-successor) (Expansion, growth as a successor Mission), and [complete](#complete-discharge-narrows-one-entry-at-a-time) (Completion, authority that retires itself). The [fail-safe rule](#the-rule-that-makes-it-safe) that ties them together is that only `active` permits reliance.
- **The card analogy.** Freeze it, cancel it, raise the limit through a fresh approval, or let it close itself out as the work finishes. [Canceling the Card Doesn't Stop the Charges](/notes/canceling-the-card-doesnt-stop-the-charges/) is this part with no protocol in sight. ([Where the analogy breaks](/notes/canceling-the-card-doesnt-stop-the-charges/#where-the-analogy-breaks).)
- **The laws.** This post operationalizes [Durability, Narrowing, and Termination (Laws 1, 3, and 4)](/series/mission-bound-authorization/#the-five-laws-of-delegated-authority): the task outlives its tokens, widening requires a fresh approval, and revocation ends authority rather than waiting for tokens to age out. (Termination is the card series' rule 5, ending the credential is not ending the arrangement.)
- **Specs (editor's copies).** [Mission Status and Lifecycle](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-status.html), [Mission Lifecycle Signals](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-signals.html), [Mission Expansion](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-expansion.html), [Mission Completion](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-completion.html), with [Mission Progressive Authorization](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-progressive.html) and [Mission Management](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-management.html) as the newer companions.

**Reading path.** ~15 minutes start to finish. Read in order.

{{< /tldr >}}

# Overview

[The Mission Is the Missing Abstraction](/notes/the-mission-is-the-missing-abstraction/) defined the Mission as a durable governance object and gave it a deliberately small lifecycle: `active`, `revoked`, `expired`, with the rule that only `active` permits new derivation. That issuance core is complete on its own. But it observes Mission state only through one channel: the lifetime of the tokens it already issued, plus optional token introspection. A consumer that holds a Mission-bound token and nothing else has no way to ask "is this Mission still good," and no way to be *told* that it stopped being good. An authorized operator who wants to pause a Mission has no standardized verb for it. A task that finishes keeps deriving its authority until a clock or a revoke stops it.

This part closes those gaps with four companion profiles, each optional, each layering on the issuance core without changing it. They are not all at the same maturity. Status is the protocol MVP's state surface. Signals, its push complement, is experimental. Expansion and Completion sit on the advanced tier, stable design to adopt when the use case arrives, and each has a newer companion noted where it attaches (Progressive Authorization and fleet Management). They answer four questions a long-running task forces:

- **Observe:** how does a consumer holding only a `mission_id` learn the current state, and learn it *promptly* when it changes?
- **Revoke:** how does an authorized party change the state (terminate, pause, resume)?
- **Grow:** what happens when the task legitimately needs more authority than was approved?
- **Complete:** how does authority retire itself safely as the work it was granted for finishes?

The unifying move is the one the [series framing](/series/mission-bound-authorization/) names as a recurring rule. **Only `active` permits reliance.** Every state these profiles add (`suspended`, `completed`, `superseded`) is treated as non-active by any consumer, including one that has never heard of it. That is what lets the lifecycle grow new states without breaking the consumers that predate them. We return to it at the end, because it is the property that makes all four verbs safe.

| The control at a glance | |
| --- | --- |
| **Minimum useful version** | The issuer serves Status (or token introspection) so any consumer holding a `mission_id` can learn current state, and every consumer treats non-`active` as no |
| **What it prevents** | A revoked or expired Mission living on until its tokens age out |
| **What it does not prevent** | Actions inside the published staleness bound. Size the polling to the risk, and evaluate the experimental Signals push where seconds matter |
| **Operational owner** | The Mission Issuer operates the Status surface and the lifecycle verbs |
| **Evidence emitted** | Every lifecycle transition, keyed by `mission_id` |
| **Maturity** | Status is the protocol MVP's state surface. Signals is experimental. Expansion and Completion are advanced |

# Observe and revoke: pull and push

The kill switch from [The Mission Is the Missing Abstraction](/notes/the-mission-is-the-missing-abstraction/) is possession-independent. Revoke the Mission at the Authorization Server and no new authority derives for the task. But "no new derivation" only bites at the next derivation event. A Resource Server holding a live access token does not consult the Authorization Server on every call by default. It trusts the token until it expires. So the kill switch is only as fast as the slowest token's remaining lifetime, unless consumers can learn the current state out of band.

There are exactly two ways to learn current state: ask for it, or be told. The suite provides both.

## Status: the pull side

[Mission Status and Lifecycle](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-status.html) defines the canonical state surface the issuance core deferred: an operation keyed by `mission_id` alone. Token introspection answers "is *this token's* authorization still good." The Status operation answers a different question, "what is the state of *this Mission*," and answers it for any consumer holding a `mission_id`, including an auditor or a cross-domain Resource Server that holds no token the Authorization Server issued. The consumer resolves the endpoint from the credential's `mission.issuer` and asks.

The answer is **signed**. A Status response is a JWS, with its own media type (`application/mission-status-response+jwt`), carrying the `mission` object (`id`, `issuer`, `authority_hash`, `state`, and the Mission's `expires_at`) plus, when the requester names an audience, the audience-scoped Authority Set entries relevant to it. An auditor may omit the audience and get a state-only response with no `authorization_details`. It is bound to the request by an echoed `nonce`, to the requester by `aud` and `sub`, and to a freshness window by `fresh_until`, which tells the consumer how long it may cache the reported state before re-checking. The signing matters because the response often outlives the call. An auditor must be able to verify, later, that the issuer really reported `revoked` at a given moment.

Two design choices in Status are worth pulling out because they are easy to get wrong:

- **A `mission_id` is never a bearer capability.** The endpoint authenticates the requester and authorizes it for the specific `mission_id` and audience. An unknown Mission and a known-but-unauthorized one return *indistinguishable* responses, so the Status surface cannot be turned into an enumeration oracle for the Mission space.
- **The dedicated operation is not RFC 9701.** Signed token introspection (RFC 9701) is scoped to token introspection and does not apply to a lookup keyed by `mission_id`. There is a separate, thinner story for the token-scoped case. The issuance core's introspection projection carries the `mission` state, and this Status profile adds the option of returning that projection as an RFC 9701-signed response. Two surfaces, two signing stories, deliberately not conflated.

Status is also where the explicit **lifecycle endpoint** lives (the verbs that change state). A management endpoint, distinct from RFC 7009 token revocation, accepts authenticated `revoke`, `suspend`, `resume`, and `complete` operations and introduces two states the issuance core did not have:

- **`suspended`:** a non-terminal pause. A suspended Mission derives no tokens, but it can be resumed to `active`. This is the "stop, but don't tear down" state an operator wants when something looks wrong but is not yet known to be malicious.
- **`completed`:** a terminal state recording that the task finished successfully.

The legal transitions are narrow on purpose: `suspend` only from `active`, `resume` only from `suspended`, `revoke` from either, `complete` from `active` or `suspended` (completion is a monotonic narrowing to a terminal state and needs no derivation window, so a suspended Mission need not be resumed first). An operation against a state it is not legal from is a *conflict*, not a silent no-op. The endpoint refuses it rather than pretending it worked. The endpoint authorizes operations against deployment policy (typically `revoke` to the Subject, Approver, or an administrator; `suspend`/`resume` to administrators), and an unauthorized request gets the same not-found response shape as an unknown Mission, so the management surface is no more of an enumeration oracle than the read surface. Fleet-scale operations are deliberately out of this profile: authenticated Mission enumeration (by subject, client, state, or expiry window) and bulk lifecycle operations with a dry-run-first discipline live in the [Mission Management](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-management.html) companion, on the advanced tier.

## Signals: the push side

Status answers when the consumer asks. But a high-assurance consumer that wants revocation to bite in seconds cannot afford to poll the Status endpoint on every action. That puts the Authorization Server on the hot path of every credential validation. The complement is to be *told*.

[Mission Lifecycle Signals](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-signals.html) is a profile of the OpenID Shared Signals Framework. When the Mission Issuer commits a lifecycle transition (a revocation, expiry, suspension, completion, or the approval event that activates the Mission), it emits a signed **Security Event Token**, a `mission.lifecycle-change` event, delivered either by push (the Issuer pushes the SET to the consumer's receiver) or by poll (the consumer fetches available SETs). A partner Resource Server subscribed to the stream learns of a cancellation seconds after it happens, well inside the remaining lifetime of any token it holds, and stops honoring the Mission.

One honesty note first. Signals is labeled experimental on the adoption ladder, and not for dependency reasons (Security Event Tokens and their delivery are ratified). Push is a latency optimization over correctly sized status polling, and the profile should earn its interface through deployment before anyone builds a hard dependency on it. The stable path is Status polling sized to the risk, with Signals adopted for evaluation where a revocation must bite in seconds.

The event carries the new `state`, the `prior_state` (except on the initial approval emission, where there is none), and a strictly monotonic per-Mission `version` counter. The counter is the part that makes event delivery safe against the network. Events can arrive out of order or be replayed, so the consumer applies a transition only if its `version` is greater than the last it applied. A stale `active` event for an older version cannot revive a Mission a newer `revoked` event already retired. And because delivery is best-effort, a consumer that cannot verify its stream, or that was down and may have missed events, treats its cached state as stale once it exceeds the Issuer's advertised staleness bound and falls back to polling Status. A missed event is a *freshness failure*, never "still active." Signals make revocation prompt. They never make it fail open.

```mermaid
flowchart LR
    subgraph AS["Mission Issuer"]
        M[("Mission record<br/>state")]
        SE[Status endpoint]
        LE[Lifecycle endpoint]
        EV[Event stream<br/>SSF / SET]
    end
    OP[Authorized party] -->|revoke / suspend<br/>resume / complete| LE
    LE --> M
    M --> SE
    M --> EV
    C1[Consumer<br/>holds mission_id] -->|PULL: ask<br/>signed response| SE
    EV -->|PUSH: told<br/>signed SET| C2[Consumer<br/>subscribed]
```

Pull and push are not alternatives so much as two sizes of the same answer. A consumer that checks state occasionally polls Status. A consumer that needs prompt revocation subscribes to Signals and falls back to Status when the stream goes quiet. Both read the same fact, the current `state`, from the same authoritative issuer.

> **The running example.** Take the [series running example](/notes/mission-bound-authorization-reference/), the *Prepare the Q3 board packet* Mission, `msn_01J9Z2P8BQ4Y3F0V0K9D6Z7M1` at `as.example.com`. The board meeting is cancelled while the agent is still drafting, so an admin **revokes** the Mission mid-draft at the lifecycle endpoint. A consumer holding only the `mission_id` (the docs Resource Server, an auditor) learns the new state without holding any token the Issuer can age out. It either asks Mission Status (pull) or receives a `mission.lifecycle-change` Signal carrying `state: revoked` (push). Either way the result is the same. `query_financials`, `create_doc`, and `notify_reviewer` all stop deriving at once.

# Grow: expansion creates a successor

The first recurring rule of the series is that authority can only *narrow*. A derived or delegated token never carries more than the Mission. The subset rule enforces it at every derivation. That is a foundational safety property, but it raises an obvious question. What happens when the task legitimately needs to do something the approved Authority Set does not cover? Mid-task, the *Prepare the Q3 board packet* agent decides it could enrich the packet by reading CRM customer data, an authority the Approver never granted, outside the Mission's `query_financials`/`create_doc`/`notify_reviewer` set entirely.

The answer is *not* to widen the Mission in place. A Mission's authority is committed at one approval event by `authority_hash`. Widening it in place would mean the thing the user approved is no longer the thing in force, and `authority_hash` would no longer commit what is being used. [Mission Expansion](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-expansion.html) instead routes growth through a *new approval that creates a successor Mission*.

An expansion is an ordinary Mission creation under the issuance core (a Mission Intent submitted through Pushed Authorization Requests, leading to a fresh approval event) with one binding added. The request is bound to the predecessor's grant (the client presents the predecessor's refresh token), so the Issuer adjudicates a successor *of a specific predecessor* rather than an unrelated new Mission. The fresh consent is what supplies the broader authority. The successor's authority comes only from its own approval. Its `authority_hash` commits exactly the set the Approver saw, never the predecessor's plus a computed delta. On the successor's activation, the predecessor transitions atomically to a terminal `superseded` state and derives nothing further. The successor carries a `predecessor` lineage member linking it back, but that member is audit context only. Like every other extra member on the `mission` claim, it MUST NOT grant or widen authority.

Two distinctions keep expansion honest:

- **Expansion is not step-up.** A request denied because authentication is too weak (an `acr`/`amr` shortfall) is satisfied by re-authentication. The Authority Set does not change. A request denied because the *authority* is not in the active Mission is what expansion addresses. Routing an authentication shortfall through an approval event would surface irrelevant consent and breed approval fatigue. Treating an authority shortfall as a mere re-auth would silently widen nothing. The two are not interchangeable.
- **Expansion is a governance operation, not a runtime escalation.** It does not undo the subset rule. It is a deliberately heavier, consent-backed path that produces a new governed object the kill switch and audit chain still cover.

For open-ended tasks where stopping the user at every step is impractical, a newer, experimental companion, [Mission Progressive Authorization](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-progressive.html), builds on expansion. At the initial approval the Approver may also consent to an *authority ceiling* and a *drawdown policy*, so in-ceiling expansions can be adjudicated by policy rather than a fresh human prompt. The ceiling is broad by construction (it has to cover the open-ended task), but what stays narrow is the active authority any single Mission in the chain yields. Each successor is derived for what is actually needed at that step, independently gated and revocable. The guard is explicit. A drawdown that would grant an irreversible action, an external commitment, privileged administration, or cross-domain authority always requires fresh human approval, even within the ceiling. Progressive authorization bounds standing-authority exposure. It does not eliminate it, and it is meant to be paired with short successor lifetimes and runtime enforcement.

> **The running example.** The *Prepare the Q3 board packet* Mission, `msn_01J9Z2P8BQ4Y3F0V0K9D6Z7M1` at `as.example.com`, cannot read CRM customer data. That authority is outside its Authority Set, and the agent cannot widen the Mission in place. So it requests an **expansion**, a fresh approval for a successor Mission bound to the predecessor's grant. The Approver **declines**. CRM access is out of policy for board-packet preparation. The result is the failsafe one. No CRM access, no successor activates, and the predecessor is untouched and still `active`, deriving exactly its original three entries. Had the expansion instead been approved, the successor would have activated and the predecessor would have transitioned atomically to `superseded`. Because it was declined, nothing supersedes anything.

# Complete: discharge narrows one entry at a time

Expansion is governed growth. Completion is its narrowing counterpart. It is the more important of the two for everyday safety, because the common case is not a task that needs more authority but a task that is *done* with some of the authority it has. Like Expansion, it sits on the advanced tier: stable design to adopt when the use case arrives, with `expires_at`, revocation, and the `complete` verb as the simpler path until then.

The [issuance core's](/notes/the-mission-is-the-missing-abstraction/) Mission Intent can carry `success_criteria`: a description of when the task is complete. In the issuance core those criteria are **inert** (rendered to the Approver, committed to the record, carrying no machine effect). A Mission granted authority to post journal entries "until the Q3 close is finalized" keeps deriving that authority after the close, until a clock or a revoke intervenes. [Mission Completion](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-completion.html) supplies the enforceable counterpart: `terminal_when`, an entry-level completion condition. When the condition fires, the entry is **discharged**. The Authorization Server stops deriving any token carrying it, exactly as it refuses derivation for a non-`active` Mission.

The crucial scope detail is that discharge gates at the *entry*, not the Mission. A multi-resource Mission completes one entry at a time. In the [running example](/notes/mission-bound-authorization-reference/), suppose the board meeting is *not* cancelled and the work finishes instead. The *Prepare the Q3 board packet* Mission has a `query_financials` read entry, a `create_doc` write entry, and a `notify_reviewer` send entry, the write and send entries each bounded `terminal_when` their step is done (`create_doc` once the packet is published, `notify_reviewer` once the audit committee is told). As each condition fires, the Authorization Server stops deriving that entry (a refresh returns a token carrying only what remains) while the Mission stays `active` so any remaining entry keeps working. Each authority retired itself the moment the task it was granted for completed. No revoke, no clock.

This is distinct from the `complete` lifecycle verb of the Status profile, and the two should not be blurred. `complete` is a *Mission-level* terminal transition to the `completed` state, driven by an authorized party at the lifecycle endpoint. `terminal_when` discharge is *entry-level*. The Mission stays `active` and keeps deriving its other entries. A deployment that tracks Mission-level completion *may* move a Mission to `completed` once all its entries are discharged, but Completion does not require it. One is "the whole task is finished." The other is "this part of the authority is spent."

What makes entry-level discharge safe to expose to an adversarial agent is that it is **monotonic**. Discharge can only *remove* an entry's authority. It can never widen the entry or the Mission. So a prompt-injected agent has nothing to gain from it. The worst it can do is spend its own authority sooner, which is not an attack. That single property is why discharge composes cleanly with the subset rule (a derived entry carries its parent's conditions unchanged and may only *add* more, making it discharge sooner) and why an Authorization Server that cannot determine whether a condition has fired fails *closed*, treating the entry as possibly discharged and withholding issuance rather than risking authority for a task that may have ended. Like the kill switch, completion is built so that uncertainty resolves toward less authority, never more.

# The rule that makes it safe

The four verbs add three new states to the lifecycle [The Mission Is the Missing Abstraction](/notes/the-mission-is-the-missing-abstraction/) began with. The state diagram now looks like this:

```mermaid
stateDiagram-v2
    [*] --> active: Approval event
    active --> revoked: revoke (user / admin / policy)
    active --> expired: expires_at reached
    active --> suspended: suspend
    active --> completed: complete
    active --> superseded: successor activates (Expansion)
    suspended --> active: resume
    suspended --> revoked: revoke
    suspended --> expired: expires_at reached
    suspended --> completed: complete
    revoked --> [*]
    expired --> [*]
    completed --> [*]
    superseded --> [*]
```

A growing state machine is a liability if every consumer must be upgraded in lockstep to recognize each new state. The Mission lifecycle avoids that with the rule the [series framing](/series/mission-bound-authorization/) states as one of its two invariants, and which the [Reference's lifecycle-states section](/notes/mission-bound-authorization-reference/#lifecycle-states) records for the core:

> Only `active` permits reliance. A consumer treats *every* other value, recognized or not, as non-active.

This is why the new states fail safe. A Resource Server that predates the Status profile has never heard of `suspended`. When it sees one (in a Status response, in an introspection projection, in a Signals event), it does not need to understand it. It only needs to observe that the value is not `active`, and refuse. A consumer that predates Expansion treats `superseded` the same way. The forward-compatibility rule turns "I don't recognize this state" into "this Mission is not live," which is precisely the safe interpretation. New lifecycle states therefore extend the system without a flag day.

The one place this "ignore what you don't recognize" instinct flips is Completion's `terminal_when`, and the difference is worth being precise about. A new *state value* is safe to ignore because an unrecognized state is treated as non-active. Ignoring it fails *closed*. But `terminal_when` is a *member*, not a state, and it is mandatory to understand. It is essential narrowing a consumer cannot infer from the rest of the entry, so ignoring it would let a discharged entry keep being narrowed, projected, or enforced, failing *open*. A consumer that does not recognize `terminal_when` therefore MUST fail closed for that entry. It MUST NOT narrow, delegate, audience-project, or rely on it. Unknown state value, treat as non-active. Unknown `terminal_when`, refuse the entry. Both resolve toward less authority, by opposite handling.

The same instinct runs through every profile in this part, each resolving uncertainty toward *less* authority:

- **Status** treats a missing freshness window as "don't cache" (re-check rather than rely on a stale state).
- **Signals** treats a missed event as a freshness failure that triggers a fallback poll, never as "still active."
- **Expansion** never widens authority without a fresh consent, and supersession is terminal. There is no implicit rollback that resurrects a predecessor's authority.
- **Completion** discharges monotonically and withholds issuance when discharge status is unknown.

That is the through-line. [The Mission Is the Missing Abstraction](/notes/the-mission-is-the-missing-abstraction/) made revocation possession-independent. This part makes the *current state itself* a first-class surface (observable by pull and push, changeable by authorized parties, growable only through fresh approval, and shrinkable safely as work finishes) without ever giving a consumer a way to read uncertainty as permission.

# Where this sits in the series

Lifecycle and change is the layer that keeps the Mission true *over time*. It does not enforce actions. That is [Mission-Bound Runtime Enforcement](/notes/mission-bound-runtime-enforcement-profile/), which consumes the state these profiles expose. Every PDP decision is conditioned on current Mission state, and Status is how the PDP learns it promptly, with Signals accelerating and Completion narrowing what there is to learn. It does not handle fan-out. [Mission-Bound Authority](/notes/mission-sub-agents-and-delegation/) covers Child Missions and the `cascaded` state that Status and Signals forward-reference but do not define. And it does not record the transitions for audit. [The Agent Runtime and Audit](/notes/mission-agent-runtime-and-audit/) makes every lifecycle change tamper-evident.

The approval event of [The Mission Is the Missing Abstraction](/notes/the-mission-is-the-missing-abstraction/) and the approval-time integrity of [From a Request to an Approved Mission](/notes/mission-approval-integrity/) establish *what was approved*. This part keeps that approval honest as the task runs. A Mission that is revoked stops being relied on, a Mission that grows does so under a fresh approval, and a Mission whose work is done retires its own authority. Observe, revoke, grow, complete. Four verbs that turn a one-time approval into a governed lifecycle.

