<?xml version="1.0" encoding="UTF-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="std"
     consensus="true"
     docName="draft-zhu-httpbis-task-context-00"
     ipr="trust200902"
     submissionType="IETF"
     xml:lang="en">
  <front>
    <title abbrev="Task-Context HTTP Field">Task-Context HTTP Field for Task Context Propagation</title>
    <author fullname="Larry Zhu" initials="L." surname="Zhu">
      <organization>Atlassian</organization>
      <address>
        <email>lzhu3@atlassian.com</email>
      </address>
    </author>
    <date year="2026" month="June" day="5"/>
    <area>Web and Internet Transport</area>
    <keyword>HTTP</keyword>
    <keyword>header field</keyword>
    <keyword>task context</keyword>
    <keyword>workflow authorization</keyword>
    <abstract>
      <t>This document defines the Task-Context HTTP field for propagating task execution context from an authorized workflow worker to downstream HTTP services. The field carries a compact, base64url-encoded JSON object that identifies the authorization mode, workflow type, and either task-based requestor and approver context or role-based execution context.</t>
      <t>The field is not a bearer credential and does not replace HTTP client authentication, service-to-service authorization, or resource-local policy checks. Its purpose is to let downstream services correlate requests with workflow task context and make service-local authorization and audit decisions using that context.</t>
    </abstract>
  </front>
  <middle>
    <section anchor="introduction" numbered="true" toc="include">
      <name>Introduction</name>
      <t>Modern automation systems often authorize a high-level workflow before any downstream API call occurs. The workflow engine can evaluate the full task intent, manifest, requestor, approver, policy evidence, and blast radius at the workflow boundary. Later, a workflow worker calls downstream HTTP APIs using its own service identity. Without a standard way to carry task context, those downstream services see an authenticated service call but cannot easily correlate that call to the human request, approval, or role that caused the workflow step.</t>
      <t>The Task-Context field provides a compact HTTP field for this correlation. It is designed for task context propagation, audit, and policy input. It is not designed as an authentication token, delegation token, or proof of approval by itself.</t>
      <t>The field name is intended for registration in the IANA Hypertext Transfer Protocol Field Name Registry. Registration avoids collisions with independently defined HTTP fields and avoids the historical "X-" prefix convention deprecated by <xref target="RFC6648"/>. Private deployment aliases are outside the scope of this registration.</t>
    </section>

    <section anchor="conventions" numbered="true" toc="include">
      <name>Conventions and Definitions</name>
      <t>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 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
      <dl newline="false" spacing="normal">
        <dt>Task:</dt>
        <dd>A unit of authorized work initiated through a workflow, job, or automation system.</dd>
        <dt>Task context:</dt>
        <dd>The metadata that links an HTTP request to the task that caused it.</dd>
        <dt>Workflow worker:</dt>
        <dd>The authenticated service component that executes workflow steps and calls downstream HTTP APIs.</dd>
        <dt>Task-based authorization:</dt>
        <dd>Authorization in which a workflow is approved based on a concrete requestor, approver, manifest, input, and policy evidence.</dd>
        <dt>Role-based execution:</dt>
        <dd>Execution in which the worker acts under an authorized role rather than a specific requestor/approver task approval.</dd>
      </dl>
    </section>

    <section anchor="field-definition" numbered="true" toc="include">
      <name>The Task-Context HTTP Field</name>
      <t>The Task-Context field value is a base64url-encoded UTF-8 JSON object without padding. The decoded JSON object is called the task context object.</t>
      <figure anchor="abnf-task-context">
        <name>Task-Context field ABNF</name>
        <sourcecode type="abnf"><![CDATA[
Task-Context = 1*( ALPHA / DIGIT / "-" / "_" )
]]></sourcecode>
      </figure>
      <t>Senders MUST NOT include more than one Task-Context field in a request. Recipients that receive multiple Task-Context fields for one request MUST reject the request or ignore all task context for that request.</t>
      <t>Recipients SHOULD impose an implementation limit on the field size. This document RECOMMENDS a maximum decoded JSON size of 4096 octets unless a deployment profile specifies a smaller limit.</t>
    </section>

    <section anchor="task-context-object" numbered="true" toc="include">
      <name>Task Context Object</name>
      <t>The decoded task context object is a JSON object. Unknown members MUST be ignored unless a local policy requires strict validation. Senders MUST omit members with no value.</t>
      <dl newline="false" spacing="normal">
        <dt>mode (required):</dt>
        <dd>Either "task-based" or "role-based".</dd>
        <dt>workflow_type (required):</dt>
        <dd>The workflow or task executor type.</dd>
        <dt>requestor (required when mode is "task-based"):</dt>
        <dd>The principal that requested the task. Deployments MAY use an opaque subject identifier instead of an email address.</dd>
        <dt>approver (optional for "task-based"):</dt>
        <dd>The principal that approved the task when approval was required or obtained. A future revision can define support for multiple approvers.</dd>
        <dt>ats_role (required when mode is "role-based"):</dt>
        <dd>The role asserted by the upstream authorization system for role-based execution.</dd>
      </dl>
    </section>

    <section anchor="sender-requirements" numbered="true" toc="include">
      <name>Sender Requirements</name>
      <ol spacing="normal" type="1">
        <li>A sender MUST authenticate to the downstream HTTP service independently of Task-Context.</li>
        <li>A workflow worker SHOULD send Task-Context only after the workflow start or task execution request has passed the applicable authorization checks.</li>
        <li>A sender MUST use base64url encoding without padding over the UTF-8 JSON representation of the task context object.</li>
        <li>A sender MUST include "mode" and "workflow_type".</li>
        <li>For task-based authorization, a sender MUST include "requestor" and SHOULD include "approver" when an approval exists.</li>
        <li>For role-based execution, a sender MUST include "ats_role".</li>
      </ol>
    </section>

    <section anchor="recipient-requirements" numbered="true" toc="include">
      <name>Recipient Requirements</name>
      <ol spacing="normal" type="1">
        <li>A recipient MUST authenticate the HTTP client before using task context.</li>
        <li>A recipient MUST NOT grant access solely because a Task-Context field is present.</li>
        <li>A recipient SHOULD validate that the authenticated caller is allowed to present task context for the requested API.</li>
        <li>A recipient SHOULD log "mode", "workflow_type", and the task-based or role-based fields that are present.</li>
        <li>A recipient MAY use the task context object as input to local authorization policy, audit, rate limiting, or abuse detection.</li>
        <li>A recipient that forwards a request as part of the same task SHOULD propagate the original Task-Context unchanged. It MUST NOT modify requestor, approver, role, or workflow values unless it is acting as a new workflow worker for a new task.</li>
      </ol>
    </section>

    <section anchor="examples" numbered="true" toc="include">
      <name>Examples</name>

      <section anchor="example-task-based" numbered="true" toc="default">
        <name>Task-Based Authorization</name>
        <t>Decoded task context:</t>
        <sourcecode type="json"><![CDATA[
{
  "mode": "task-based",
  "workflow_type": "UpdateServiceConfigWorkflow",
  "requestor": "alice@atlassian.com",
  "approver": "bob@atlassian.com"
}
]]></sourcecode>
        <t>HTTP request:</t>
        <sourcecode type="http-message"><![CDATA[
POST /v1/objects HTTP/1.1
Host: config-registry.example.net
Authorization: Bearer <service-token>
Task-Context: eyJhcHByb3ZlciI6ImJvYkBhdGxhc3NpYW4uY29tIiwibW9kZSI6InRhc2stYmFzZWQiLCJyZXF1ZXN0b3IiOiJhbGljZUBhdGxhc3NpYW4uY29tIiwid29ya2Zsb3dfdHlwZSI6IlVwZGF0ZVNlcnZpY2VDb25maWdXb3JrZmxvdyJ9
Content-Type: application/yaml

...
]]></sourcecode>
      </section>

      <section anchor="example-role-based" numbered="true" toc="default">
        <name>Role-Based Execution</name>
        <t>Decoded task context:</t>
        <sourcecode type="json"><![CDATA[
{
  "mode": "role-based",
  "workflow_type": "ReadOnlyInventoryWorkflow",
  "ats_role": "amp-service-config-reader"
}
]]></sourcecode>
        <t>HTTP request:</t>
        <sourcecode type="http-message"><![CDATA[
GET /v1/inventory HTTP/1.1
Host: inventory.example.net
Authorization: Bearer <service-token>
Task-Context: eyJhdHNfcm9sZSI6ImFtcC1zZXJ2aWNlLWNvbmZpZy1yZWFkZXIiLCJtb2RlIjoicm9sZS1iYXNlZCIsIndvcmtmbG93X3R5cGUiOiJSZWFkT25seUludmVudG9yeVdvcmtmbG93In0
]]></sourcecode>
      </section>
    </section>

    <section anchor="relationship-to-auth" numbered="true" toc="include">
      <name>Relationship to Authentication and Authorization</name>
      <t>Task-Context is task context, not proof of identity. Deployments MUST continue to use their normal HTTP client authentication mechanism, such as OAuth access tokens, mutual TLS, service mesh identity, or platform-native service identity. Downstream services SHOULD combine the authenticated caller, requested resource, local policy, and task context when making authorization decisions.</t>
      <t>When a workflow worker calls downstream APIs, the downstream service can verify that the caller is an allowed worker, then use the decoded Task-Context value as local policy and audit input. If stronger integrity is required across an untrusted boundary, deployments SHOULD bind a cryptographic hash of the exact Task-Context field value into an integrity-protected service-authentication envelope or a companion signed assertion rather than relying on the unsigned header value alone.</t>
    </section>

    <section anchor="security-considerations" numbered="true" toc="include">
      <name>Security Considerations</name>
      <t>Any HTTP client can construct a Task-Context value. Recipients MUST authenticate callers and MUST NOT treat the field as a bearer credential.</t>
      <t>Gateways and edge services SHOULD remove inbound Task-Context fields from untrusted clients unless the client is explicitly allowed to set task context.</t>
      <t>A copied field value can be replayed. Recipients that use task context for policy SHOULD bind decisions to the authenticated caller, target API, resource, and current policy state.</t>
      <t>Base64url encoding avoids control characters in the field value. Recipients MUST reject values that are not valid base64url, are not valid UTF-8 JSON after decoding, exceed local size limits, or decode to a non-object JSON value.</t>
      <t>A downstream service MUST avoid granting the worker broader access than the approved task allows. Task context is one policy input; resource-local authorization remains required.</t>
      <t>This document does not define a signature format. Deployments that need cryptographic integrity SHOULD sign the task context or carry the equivalent data in an existing signed token, while preserving Task-Context as the correlation field.</t>
    </section>

    <section anchor="privacy-considerations" numbered="true" toc="include">
      <name>Privacy Considerations</name>
      <t>The task context object can contain personal data, including requestor and approver identifiers. Senders SHOULD minimize these values, prefer stable opaque subject identifiers where possible, and avoid putting sensitive ticket text, comments, or free-form justification in the header.</t>
      <t>Recipients SHOULD treat logs containing Task-Context as security and audit logs with appropriate retention and access controls.</t>
    </section>

    <section anchor="iana-considerations" numbered="true" toc="include">
      <name>IANA Considerations</name>
      <t>This document requests permanent registration of the "Task-Context" HTTP field name in the "Hypertext Transfer Protocol (HTTP) Field Name Registry".</t>
      <ul spacing="normal">
        <li>Field Name: Task-Context</li>
        <li>Status: permanent</li>
        <li>Structured Type: no</li>
        <li>Reference: this document</li>
        <li>Comments: Carries a base64url-encoded JSON task context object.</li>
      </ul>
      <t>This registration is the collision-avoidance mechanism for the standards-track field name. Private deployment aliases are not registered by this document.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>Normative References</name>
      <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author initials="S." surname="Bradner" fullname="Scott Bradner"/>
          <date month="March" year="1997"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
      </reference>
      <reference anchor="RFC4648" target="https://www.rfc-editor.org/info/rfc4648">
        <front>
          <title>The Base16, Base32, and Base64 Data Encodings</title>
          <author initials="S." surname="Josefsson" fullname="Simon Josefsson"/>
          <date month="October" year="2006"/>
        </front>
        <seriesInfo name="RFC" value="4648"/>
      </reference>
      <reference anchor="RFC6648" target="https://www.rfc-editor.org/info/rfc6648">
        <front>
          <title>Deprecating the "X-" Prefix and Similar Constructs in Application Protocols</title>
          <author initials="P." surname="Saint-Andre" fullname="Peter Saint-Andre"/>
          <author initials="D." surname="Crocker" fullname="Dave Crocker"/>
          <author initials="M." surname="Nottingham" fullname="Mark Nottingham"/>
          <date month="June" year="2012"/>
        </front>
        <seriesInfo name="BCP" value="178"/>
        <seriesInfo name="RFC" value="6648"/>
      </reference>
      <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author initials="B." surname="Leiba" fullname="Barry Leiba"/>
          <date month="May" year="2017"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
      </reference>
      <reference anchor="RFC8259" target="https://www.rfc-editor.org/info/rfc8259">
        <front>
          <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
          <author initials="T." surname="Bray" fullname="Tim Bray"/>
          <date month="December" year="2017"/>
        </front>
        <seriesInfo name="RFC" value="8259"/>
      </reference>
      <reference anchor="RFC9110" target="https://www.rfc-editor.org/info/rfc9110">
        <front>
          <title>HTTP Semantics</title>
          <author initials="R." surname="Fielding" fullname="Roy T. Fielding"/>
          <author initials="M." surname="Nottingham" fullname="Mark Nottingham"/>
          <author initials="J." surname="Reschke" fullname="Julian Reschke"/>
          <date month="June" year="2022"/>
        </front>
        <seriesInfo name="RFC" value="9110"/>
      </reference>
    </references>

    <references>
      <name>Informative References</name>
      <reference anchor="Trace-Context" target="https://www.w3.org/TR/trace-context/">
        <front>
          <title>Trace Context</title>
          <author fullname="World Wide Web Consortium" surname="Consortium">
            <organization>W3C</organization>
          </author>
          <date month="November" year="2021"/>
        </front>
      </reference>
    </references>
  </back>
</rfc>
