<?xml version="1.0" encoding="UTF-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     ipr="trust200902"
     category="info"
     submissionType="IETF"
     docName="draft-acosta-crypto-agility-manifest-01"
     version="3"
     consensus="false">

  <front>
    <title abbrev="Crypto-Agility Manifest">A Well-Known URI and JSON Format for Publishing Cryptographic Posture (the Crypto-Agility Manifest)</title>
    <seriesInfo name="Internet-Draft" value="draft-acosta-crypto-agility-manifest-01"/>

    <author fullname="Leon Acosta" initials="L." surname="Acosta">
      <organization>QuantaKrypto</organization>
      <address>
        <postal>
          <country>Argentina</country>
        </postal>
        <email>leon@quantakrypto.com</email>
      </address>
    </author>

    <date year="2026" month="August" day="7"/>

    <area>Security</area>
    <keyword>crypto-agility</keyword>
    <keyword>post-quantum</keyword>
    <keyword>well-known URI</keyword>
    <keyword>CBOM</keyword>
    <keyword>cryptographic posture</keyword>

    <abstract>
      <t>
        This document defines a discoverable, machine-readable JSON document, the
        crypto-agility manifest, that a website or source repository publishes at
        the well-known URI "/.well-known/crypto-agility.json" to declare its
        cryptographic posture: a readiness summary, a compact Cryptography Bill of
        Materials (CBOM) summary, an optional link to a posture attestation, the
        migration policy it measures itself against, and an optional self-declared
        conformance statement with justified exceptions. The manifest lets an automated
        consumer, such as an AI coding agent, a continuous-integration bot, or an
        auditor's tool, discover a project's crypto posture the way it already
        discovers a security contact from "security.txt". The manifest is a public,
        self-reported claim; it is not a proof. It is intended to complement, not
        replace, a full CBOM inventory, serving as the CBOM's public-facing
        discovery counterpart.
      </t>
      <t>
        This document is a proposal. It is not an IETF product and is not a standard
        of any kind.
      </t>
    </abstract>
  </front>

  <middle>

    <section anchor="introduction">
      <name>Introduction</name>
      <t>
        Crypto-agility, the capability to replace and adapt cryptographic algorithms
        while preserving security and operations, is a mature and well-documented
        objective. It is treated at the algorithm-agility level by
        <xref target="RFC7696"/>, and at the organizational and lifecycle level by
        <xref target="NIST-CSWP-39"/>. Mechanism-level guidance for deriving keys when a
        classical and a post-quantum exchange are combined appears in
        <xref target="NIST-SP-800-56C"/>, and security-evaluation criteria for quantum
        key distribution in <xref target="ISO-IEC-23837"/>. The migration timelines that give crypto-agility
        its present urgency are set out in <xref target="NSM-10"/> and
        <xref target="NIST-IR-8547"/>, and general engineering guidance for the
        post-quantum transition itself is collected in <xref target="RFC9958"/>. The
        inventory of what cryptography a system
        actually uses now has a standard representation, the Cryptography Bill of
        Materials (CBOM) defined in <xref target="CycloneDX-CBOM"/>.
      </t>
      <t>
        What is missing is not the concept and not the inventory format. It is a
        conventional, discoverable place for a project to publish a short, public
        summary of its posture that a machine can find and read without out-of-band
        configuration. Automated agents increasingly make dependency and cryptography
        choices, and continuous-integration systems increasingly gate on them, but
        there is no standard location from which such a consumer can learn a project's
        crypto posture, policy, and migration deadlines. Today every such integration
        is bespoke.
      </t>
      <t>
        This document fills exactly that gap and no more. It borrows its structural
        model directly from "security.txt" <xref target="RFC9116"/>: a small file at a
        registered well-known location <xref target="RFC8615"/> that any party can
        fetch from an origin alone. Where "security.txt" publishes how to report a
        vulnerability, the crypto-agility manifest publishes a project's cryptographic
        posture. A full CBOM answers "what cryptography is in here"; the manifest is
        its public-facing discovery counterpart, answering "where do I find this
        project's posture, and what does it summarize to".
      </t>
      <t>
        The manifest is deliberately a summary and not a replacement for a full CBOM
        or a detailed readiness report. It is small enough to fetch and parse on every
        CI run, and it answers three questions at a glance: how ready is this project,
        what quantum-vulnerable cryptography is it still using, and by when has it
        committed to migrate. A consumer that needs component-level detail follows the
        CBOM pointer the manifest carries.
      </t>

      <section anchor="scope">
        <name>Scope and Non-Goals</name>
        <t>
          This document specifies the well-known URI, the media type, and the JSON
          field definitions of the manifest. It does not define a new cryptographic
          mechanism, a new attestation format, or a new CBOM format; it references the
          CBOM format of <xref target="CycloneDX-CBOM"/> for the summary it carries.
          It does not specify how a producer computes a readiness score, and it does
          not define the trust model of the credential an "attestation" link points
          to. The manifest is a self-reported claim (see
          <xref target="operational"/>); establishing whether that claim is true is
          out of scope and is the job of the linked attestation and of the consumer.
        </t>
      </section>
    </section>

    <section anchor="terminology">
      <name>Terminology and Conventions</name>
      <t>
        The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
        "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>",
        "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>",
        "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
        "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" 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>
      <t>
        The following terms are used in this document:
      </t>
      <dl newline="false" spacing="normal">
        <dt>manifest:</dt>
        <dd>the JSON document defined by this specification.</dd>
        <dt>producer:</dt>
        <dd>the party or tool that generates and publishes a manifest.</dd>
        <dt>consumer:</dt>
        <dd>any party that retrieves and interprets a manifest, for example an agent, a
          CI system, a scanner, or an auditor's tool.</dd>
        <dt>origin:</dt>
        <dd>as defined in <xref target="RFC9110"/>, the scheme, host, and port from
          which the manifest is retrieved.</dd>
        <dt>CBOM:</dt>
        <dd>a Cryptography Bill of Materials as defined in
          <xref target="CycloneDX-CBOM"/>.</dd>
        <dt>classical public-key cryptography:</dt>
        <dd>public-key algorithms, such as RSA and elliptic-curve Diffie-Hellman, whose
          security is broken by a cryptographically relevant quantum computer.</dd>
      </dl>
      <t>
        Field names, JSON literals, and example values are shown in a monospaced font.
        JSON types are as defined by the JSON grammar: object, array, string, number,
        boolean, and null. In this document, "integer" denotes a JSON number with no
        fractional part.
      </t>
    </section>

    <section anchor="well-known-uri">
      <name>The Well-Known URI</name>
      <t>
        A producer publishes its manifest at the path "/.well-known/crypto-agility.json"
        of an origin, that is:
      </t>
      <artwork><![CDATA[
https://example.com/.well-known/crypto-agility.json
]]></artwork>
      <t>
        This location uses the well-known URI mechanism of
        <xref target="RFC8615"/>, the same mechanism that hosts "security.txt"
        <xref target="RFC9116"/>. Registration of the URI suffix "crypto-agility.json"
        is requested in <xref target="iana"/>. A consumer that knows only an origin
        <bcp14>MUST</bcp14> be able to locate the manifest by resolving this path
        against that origin, with no out-of-band configuration.
      </t>
      <t>
        A manifest published for a website or service <bcp14>SHOULD</bcp14> be served
        from the origin's web root at the path above. A manifest that describes a
        source repository <bcp14>MAY</bcp14> additionally be committed into the
        repository at "/.well-known/crypto-agility.json" so that it travels with the
        source and can be regenerated by continuous integration.
      </t>
      <t>
        A manifest retrieved over HTTP or HTTPS <bcp14>SHOULD</bcp14> be retrieved over
        HTTPS (see <xref target="security"/>). A consumer <bcp14>MUST NOT</bcp14>
        follow a cross-origin redirect to locate a manifest without treating the result
        as belonging to the redirect target rather than the original origin.
      </t>
    </section>

    <section anchor="file-format">
      <name>File Format</name>
      <t>
        The manifest is a single JSON <xref target="RFC8259"/> object encoded in UTF-8.
        When served over HTTP, it <bcp14>SHOULD</bcp14> be served with a "Content-Type"
        header field <xref target="RFC9110"/> of "application/json". A consumer
        <bcp14>MUST</bcp14> reject a document that is not a single JSON object.
      </t>
      <t>
        The top-level "version" field is the schema contract. A consumer
        <bcp14>MUST</bcp14> branch on "version" and <bcp14>MUST</bcp14> reject a value
        it does not understand. This document defines "version" 1. Additive,
        backward-compatible fields <bcp14>MAY</bcp14> be introduced under "version" 1;
        any breaking change bumps "version". A consumer <bcp14>MUST</bcp14> ignore
        object members it does not recognize, so that additive fields do not break older
        consumers.
      </t>
      <t>
        The manifest is public by design. It <bcp14>MUST NOT</bcp14> contain secrets,
        source snippets, file contents, or any data not intended for public disclosure
        (see <xref target="security"/>).
      </t>
    </section>

    <section anchor="fields">
      <name>Field Definitions</name>
      <t>
        The manifest object has the members defined in this section. Unless a member is
        explicitly marked optional, it is <bcp14>REQUIRED</bcp14> and a conforming
        producer <bcp14>MUST</bcp14> emit it. A machine-readable JSON Schema for
        "version" 1 accompanies this specification.
      </t>

      <section anchor="field-version">
        <name>version</name>
        <t>
          An integer. The manifest schema version. For this specification the value
          <bcp14>MUST</bcp14> be 1. A consumer <bcp14>MUST</bcp14> reject a version it
          does not understand.
        </t>
      </section>

      <section anchor="field-manifesttype">
        <name>manifestType</name>
        <t>
          A string. A discriminator that lets a consumer distinguish this document from
          other JSON served at a well-known path. The value <bcp14>MUST</bcp14> be the
          string "crypto-agility". A consumer <bcp14>MUST</bcp14> reject a document
          whose "manifestType" is any other value.
        </t>
      </section>

      <section anchor="field-generatedat">
        <name>generatedAt</name>
        <t>
          A string. The instant the manifest was generated, formatted as an
          Internet timestamp per <xref target="RFC3339"/> (a profile of ISO 8601).
          A producer <bcp14>MUST</bcp14> set this from its runtime clock at generation
          time.
        </t>
      </section>

      <section anchor="field-generator">
        <name>generator</name>
        <t>
          An object describing what produced the manifest. It has two
          <bcp14>REQUIRED</bcp14> string members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>name:</dt>
          <dd>the name of the producing tool.</dd>
          <dt>version:</dt>
          <dd>the version of the producing tool.</dd>
        </dl>
      </section>

      <section anchor="field-subject">
        <name>subject</name>
        <t>
          An object identifying what the manifest describes. It has three
          <bcp14>REQUIRED</bcp14> members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>root:</dt>
          <dd>a string. The scanned root the manifest describes.</dd>
          <dt>repository:</dt>
          <dd>a string or null. The source repository the manifest describes.
            <bcp14>MUST</bcp14> be null when unknown.</dd>
          <dt>commit:</dt>
          <dd>a string or null. The commit identifier the manifest was derived from.
            <bcp14>MUST</bcp14> be null when unknown.</dd>
        </dl>
      </section>

      <section anchor="field-posture">
        <name>posture</name>
        <t>
          An object carrying the distilled cryptographic posture. It has four
          <bcp14>REQUIRED</bcp14> members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>readinessScore:</dt>
          <dd>a number from 0 to 100 inclusive. A producer-defined readiness score. A
            value of 100 means no classical asymmetric cryptography was found. This
            document does not define how the score is computed; a consumer
            <bcp14>MUST NOT</bcp14> assume that scores from different producers are
            directly comparable.</dd>
          <dt>hybridKexInUse:</dt>
          <dd>a boolean or null. Whether the subject negotiates hybrid post-quantum key
            exchange. A producer that cannot determine this (for example a static
            source scan, which cannot observe a negotiated key-exchange group)
            <bcp14>MUST</bcp14> set null. A consumer <bcp14>MUST</bcp14> treat null as
            "unknown", distinct from false.</dd>
          <dt>quantumVulnerable:</dt>
          <dd>an object with a <bcp14>REQUIRED</bcp14> integer member "total" (the count
            of quantum-vulnerable findings) and a <bcp14>REQUIRED</bcp14> object member
            "bySeverity". "bySeverity" <bcp14>MUST</bcp14> contain all five integer keys
            "critical", "high", "medium", "low", and "info", each a count that
            <bcp14>MUST NOT</bcp14> be negative.</dd>
          <dt>hndlExposedCount:</dt>
          <dd>an integer. The number of findings exposed to harvest-now-decrypt-later,
            that is, data that can be recorded today and decrypted once a
            cryptographically relevant quantum computer exists.</dd>
        </dl>
      </section>

      <section anchor="field-cbomsummary">
        <name>cbomSummary</name>
        <t>
          An object that summarizes, and points to, the full CBOM
          <xref target="CycloneDX-CBOM"/> from which it was derived. The full CBOM is
          intentionally not inlined, so that the manifest stays small. It has three
          <bcp14>REQUIRED</bcp14> members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>serialNumber:</dt>
          <dd>a string. The CycloneDX "serialNumber" (a "urn:uuid:" value) of the full
            CBOM this summary was derived from. This links the manifest to a specific
            CBOM instance.</dd>
          <dt>assetCount:</dt>
          <dd>an integer. The number of distinct "cryptographic-asset" components in the
            full CBOM.</dd>
          <dt>algorithmFamilies:</dt>
          <dd>an array of objects, ordered most-referenced first. Each element has a
            <bcp14>REQUIRED</bcp14> string "family" (the algorithm family name, for
            example "RSA" or "ECDH"), a <bcp14>REQUIRED</bcp14> integer "count" (the
            number of references to that family), and a <bcp14>REQUIRED</bcp14> boolean
            "quantumVulnerable".</dd>
        </dl>
      </section>

      <section anchor="field-attestation">
        <name>attestation (optional)</name>
        <t>
          An <bcp14>OPTIONAL</bcp14> object. When present, it has one
          <bcp14>REQUIRED</bcp14> string member:
        </t>
        <dl newline="false" spacing="normal">
          <dt>url:</dt>
          <dd>a URI locating a machine-verifiable posture credential. A producer
            <bcp14>MUST</bcp14> record the URI verbatim and <bcp14>MUST NOT</bcp14> be
            required to fetch it when generating the manifest. A producer
            <bcp14>MUST</bcp14> omit the "attestation" member entirely when no credential
            is declared, rather than emitting an empty or null value.</dd>
        </dl>
        <t>
          The presence of an "attestation" link does not by itself make the manifest
          verifiable; it points a consumer to where verification can be performed. See
          <xref target="operational"/>.
        </t>
      </section>

      <section anchor="field-policy">
        <name>policy</name>
        <t>
          An object stating the migration policy the subject declares it is measured
          against. It has five <bcp14>REQUIRED</bcp14> members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>source:</dt>
          <dd>a string. A label for the policy source: a published standard's name, or
            the literal "operator-declared" when the deadlines are set by the operator
            rather than adopted from a standard.</dd>
          <dt>deprecateClassicalAfter:</dt>
          <dd>an integer year after which classical public-key cryptography is
            considered deprecated under the declared policy.</dd>
          <dt>disallowClassicalAfter:</dt>
          <dd>an integer year after which classical public-key cryptography is
            considered disallowed under the declared policy.</dd>
          <dt>transitionDeadline:</dt>
          <dd>a string or null. An operator-declared migration deadline (an
            <xref target="RFC3339"/> date or a year), or null when none is declared.</dd>
          <dt>citation:</dt>
          <dd>a string. A human-readable citation for the declared deadlines.</dd>
        </dl>
        <t>
          The values of "deprecateClassicalAfter" and "disallowClassicalAfter" are the
          policy the subject holds itself to; they are a declaration, not a
          verification. A producer that adopts a published timeline
          <bcp14>SHOULD</bcp14> name it in "source" and "citation", for example the
          2030 and 2035 milestones of <xref target="NIST-IR-8547"/> and
          <xref target="NSM-10"/>. National-security profiles such as the milestones of
          <xref target="NSM-10"/> are a valid "operator-declared" choice.
        </t>
      </section>

      <section anchor="field-conformance">
        <name>conformance (optional)</name>
        <t>
          An <bcp14>OPTIONAL</bcp14> object stating the subject's self-declared
          conformance to the policy in <xref target="field-policy"/>, together with any
          residual quantum-vulnerable findings it accepts. It lets a subject that is not
          at a readiness score of 100 declare that its remaining classical cryptography
          is known and accepted under the policy, not an oversight. When present,
          it has two <bcp14>REQUIRED</bcp14> members and two <bcp14>OPTIONAL</bcp14>
          members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>policy:</dt>
          <dd>a string naming the policy the conformance is asserted against. It
            <bcp14>SHOULD</bcp14> match the "source" member of the "policy" object.</dd>
          <dt>status:</dt>
          <dd>a string, one of "conformant", "conditional", or "nonconformant".
            "conformant" means the subject meets the declared policy outright.
            "conditional" means the subject does not meet the numeric bar, but every
            residual quantum-vulnerable finding is enumerated in "exceptions" with a
            justification. "nonconformant" means residual findings exist without accepted
            exceptions.</dd>
          <dt>statement:</dt>
          <dd>an <bcp14>OPTIONAL</bcp14> string carrying a human-readable rationale for
            the status.</dd>
          <dt>exceptions:</dt>
          <dd>an <bcp14>OPTIONAL</bcp14> array of the residual findings the subject
            accepts. Each element is an object with a <bcp14>REQUIRED</bcp14> "family"
            string (the algorithm family or finding the exception covers, for example
            "RSA" or "X25519"), a <bcp14>REQUIRED</bcp14> "justification" string, and an
            <bcp14>OPTIONAL</bcp14> "acceptedUntil" integer year (typically aligned with a
            policy deadline) or null.</dd>
        </dl>
        <t>
          A self-published "conformance" status is a claim of the same kind as every other
          value in this document, not a proof (<xref target="security"/>). A consumer
          <bcp14>MUST NOT</bcp14> treat a "conformant" or "conditional" status as assurance
          unless the manifest also carries an "attestation" (<xref
          target="field-attestation"/>) that covers the asserted conformance and that the
          consumer has verified. A producer that emits a "conformant" or "conditional"
          status <bcp14>SHOULD</bcp14> also provide an "attestation".
        </t>
      </section>
    </section>

    <section anchor="examples">
      <name>Examples</name>
      <t>
        The following is a complete, conforming manifest for a repository that has
        migrated most, but not all, of its key exchange to hybrid post-quantum key
        exchange, still uses RSA and ECDH in two places, and adopts the
        <xref target="NIST-IR-8547"/> transition timeline.
      </t>
      <sourcecode type="json"><![CDATA[
{
  "version": 1,
  "manifestType": "crypto-agility",
  "generatedAt": "2026-07-27T04:57:12.323Z",
  "generator": { "name": "qScan", "version": "0.5.0" },
  "subject": {
    "root": ".",
    "repository": "https://github.com/acme/widget-service",
    "commit": "9f2c1ab7d3e04c5b8a6f0e21d47c9b3e5a1f8c02"
  },
  "posture": {
    "readinessScore": 74,
    "hybridKexInUse": true,
    "quantumVulnerable": {
      "total": 2,
      "bySeverity": {
        "critical": 0, "high": 2, "medium": 0, "low": 0, "info": 0
      }
    },
    "hndlExposedCount": 2
  },
  "cbomSummary": {
    "serialNumber": "urn:uuid:5834348b-e27b-4f71-8752-f0497d98166f",
    "assetCount": 2,
    "algorithmFamilies": [
      { "family": "ECDH", "count": 1, "quantumVulnerable": true },
      { "family": "RSA", "count": 1, "quantumVulnerable": true }
    ]
  },
  "attestation": { "url": "https://quantakrypto.com/attest/acme" },
  "policy": {
    "source": "NIST IR 8547",
    "deprecateClassicalAfter": 2030,
    "disallowClassicalAfter": 2035,
    "transitionDeadline": null,
    "citation": "https://csrc.nist.gov/pubs/ir/8547/ipd"
  },
  "conformance": {
    "policy": "NIST IR 8547",
    "status": "conditional",
    "statement": "Residual classical crypto is transition-accepted.",
    "exceptions": [
      {
        "family": "ECDH",
        "justification": "classical half of a hybrid KEX",
        "acceptedUntil": 2030
      },
      {
        "family": "RSA",
        "justification": "public-TLS cert chain; no PQC CA path yet",
        "acceptedUntil": 2030
      }
    ]
  }
}
]]></sourcecode>
      <t>
        The "conformance" object above is optional. Because its "status" is
        "conditional", the "attestation" link is what lets a consumer treat it as more
        than a claim (<xref target="field-conformance"/>). A producer that cannot observe
        live key exchange (a static source scan) sets "hybridKexInUse" to null and omits
        both "attestation" and "conformance" when neither is declared.
      </t>
    </section>

    <section anchor="operational">
      <name>Operational Considerations</name>
      <t>
        <strong>The manifest is a self-reported claim.</strong> Every value in it is
        asserted by the producer about itself. On its own the manifest establishes what
        a project says about its posture, not what is true of it. This is the same
        trust posture as "security.txt": publishing a file does not prove the
        statements in it.
      </t>
      <t>
        The "attestation" link is the bridge from claim to evidence. It points a
        consumer to a machine-verifiable posture credential that a third party can
        check independently of the manifest. A consumer that needs assurance rather
        than a claim <bcp14>SHOULD</bcp14> follow "attestation.url" and verify the
        credential there; the manifest itself <bcp14>SHOULD NOT</bcp14> be treated as
        proof of the posture it reports. A manifest without an "attestation" member is
        an unverified self-declaration and <bcp14>SHOULD</bcp14> be consumed as such.
      </t>
      <t>
        The manifest and its CBOM summary <bcp14>SHOULD</bcp14> be derived from the same
        underlying scan and CBOM, so that the summary can never contradict the full
        CBOM referenced by "cbomSummary.serialNumber". A consumer that needs
        component-level detail follows that pointer to the full CBOM rather than
        relying on the summary.
      </t>
      <t>
        Producers <bcp14>SHOULD</bcp14> regenerate the manifest as posture changes, for
        example on each CI run, so that a stale manifest does not misrepresent a project
        that has since migrated or regressed. "generatedAt" lets a consumer judge
        freshness and reject a manifest that is older than a policy it enforces.
      </t>
      <t>
        <strong>Relationship to security.txt.</strong> An origin that already publishes a
        "security.txt" file <xref target="RFC9116"/> <bcp14>SHOULD</bcp14> co-locate this
        manifest beside it under "/.well-known/", so that an operator who maintains one
        maintains the other and the two describe a consistent security posture. RFC 9116
        does not define a field for pointing at an arbitrary well-known resource, and its
        "Encryption" field is reserved for a key or a certificate used to encrypt a
        report to the operator, not for a posture document; a producer
        <bcp14>MUST NOT</bcp14> repurpose "Encryption" to reference this manifest. Where an
        operator wishes to make the link explicit, they <bcp14>MAY</bcp14> add a comment
        line to "security.txt" naming the manifest's well-known location. A consumer that
        has discovered a "security.txt" file <bcp14>SHOULD</bcp14> attempt to resolve this
        manifest at its own well-known path independently, rather than relying on any such
        reference.
      </t>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      <t>
        <strong>A manifest is a claim, not a proof.</strong> Nothing about serving a
        manifest establishes that its contents are accurate. A consumer
        <bcp14>MUST NOT</bcp14> treat a manifest as an authenticated statement of
        posture; a consumer that requires assurance <bcp14>MUST</bcp14> obtain it from a
        verifiable credential (see <xref target="operational"/>), not from the manifest
        alone. A hostile or careless producer can overstate readiness, understate
        vulnerable findings, or advertise deadlines it does not meet. A consumer that
        gates a decision on an unverified manifest inherits that risk.
      </t>
      <t>
        <strong>Self-declared conformance is not a pass.</strong> The optional
        "conformance" object (<xref target="field-conformance"/>) lets a producer assert
        a "conformant" or "conditional" status and enumerate accepted exceptions. This is
        a producer's own assertion and carries no more weight than the readiness score
        itself. A consumer <bcp14>MUST NOT</bcp14> treat a self-published status as a
        pass, an approval, or evidence of accepted risk unless the manifest also carries
        an "attestation" (<xref target="field-attestation"/>) that covers the asserted
        conformance and that the consumer has independently verified. Absent a verified
        attestation, the "status" and "exceptions" are informative context for a human
        reviewer, not an authorization to proceed.
      </t>
      <t>
        <strong>Do not leak internal detail.</strong> The manifest is public. A producer
        <bcp14>MUST NOT</bcp14> place secrets, key material, source snippets, file
        paths, internal hostnames, or any non-public detail in it. The fields defined
        here are deliberately coarse summaries for this reason. A precise public
        inventory of which quantum-vulnerable algorithms a system still uses, and where
        it is exposed to harvest-now-decrypt-later, is also a roadmap for an attacker;
        a producer <bcp14>SHOULD</bcp14> weigh the transparency benefit of a detailed
        posture against the reconnaissance value it hands an adversary, and
        <bcp14>MAY</bcp14> publish only the coarse summary this document defines.
      </t>
      <t>
        <strong>Retrieve over TLS.</strong> A manifest retrieved over the network
        <bcp14>SHOULD</bcp14> be retrieved over HTTPS, so that a network attacker cannot
        substitute or tamper with it in transit. A consumer <bcp14>SHOULD</bcp14>
        reject, or clearly mark as untrusted, a manifest retrieved over an unauthenticated
        channel. As with "security.txt" <xref target="RFC9116"/>, a cross-origin
        redirect encountered while retrieving a manifest <bcp14>MUST NOT</bcp14> be
        treated as authoritative for the original origin.
      </t>
      <t>
        <strong>Freshness and denial of service.</strong> A stale manifest can
        misrepresent current posture; consumers <bcp14>SHOULD</bcp14> use "generatedAt"
        to bound acceptable age. Because the manifest is fetched automatically and
        potentially often, producers <bcp14>SHOULD</bcp14> serve it as a static
        resource, and consumers <bcp14>SHOULD</bcp14> bound the size they will read and
        cache results, so that manifest retrieval is not turned into a denial-of-service
        vector against either party.
      </t>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>
        IANA is requested to register the following well-known URI in the "Well-Known
        URIs" registry defined by <xref target="RFC8615"/>.
      </t>
      <dl newline="false" spacing="normal">
        <dt>URI suffix:</dt>
        <dd>crypto-agility.json</dd>
        <dt>Change controller:</dt>
        <dd>IETF</dd>
        <dt>Specification document(s):</dt>
        <dd>This document.</dd>
        <dt>Status:</dt>
        <dd>permanent</dd>
        <dt>Related information:</dt>
        <dd>The resource is a JSON <xref target="RFC8259"/> document with media type
          "application/json". See <xref target="file-format"/>.</dd>
      </dl>
      <t>
        This document registers no new media type; the manifest uses the existing
        "application/json" media type.
      </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="S. Bradner"/>
          <date year="1997" month="March"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </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="B. Leiba"/>
          <date year="2017" month="May"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </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="T. Bray" role="editor"/>
          <date year="2017" month="December"/>
        </front>
        <seriesInfo name="STD" value="90"/>
        <seriesInfo name="RFC" value="8259"/>
        <seriesInfo name="DOI" value="10.17487/RFC8259"/>
      </reference>

      <reference anchor="RFC3339" target="https://www.rfc-editor.org/info/rfc3339">
        <front>
          <title>Date and Time on the Internet: Timestamps</title>
          <author initials="G." surname="Klyne" fullname="G. Klyne"/>
          <author initials="C." surname="Newman" fullname="C. Newman"/>
          <date year="2002" month="July"/>
        </front>
        <seriesInfo name="RFC" value="3339"/>
        <seriesInfo name="DOI" value="10.17487/RFC3339"/>
      </reference>

      <reference anchor="RFC8615" target="https://www.rfc-editor.org/info/rfc8615">
        <front>
          <title>Well-Known Uniform Resource Identifiers (URIs)</title>
          <author initials="M." surname="Nottingham" fullname="M. Nottingham"/>
          <date year="2019" month="May"/>
        </front>
        <seriesInfo name="RFC" value="8615"/>
        <seriesInfo name="DOI" value="10.17487/RFC8615"/>
      </reference>

      <reference anchor="RFC9110" target="https://www.rfc-editor.org/info/rfc9110">
        <front>
          <title>HTTP Semantics</title>
          <author initials="R." surname="Fielding" fullname="R. Fielding" role="editor"/>
          <author initials="M." surname="Nottingham" fullname="M. Nottingham" role="editor"/>
          <author initials="J." surname="Reschke" fullname="J. Reschke" role="editor"/>
          <date year="2022" month="June"/>
        </front>
        <seriesInfo name="STD" value="97"/>
        <seriesInfo name="RFC" value="9110"/>
        <seriesInfo name="DOI" value="10.17487/RFC9110"/>
      </reference>

      <reference anchor="CycloneDX-CBOM" target="https://cyclonedx.org/capabilities/cbom/">
        <front>
          <title>CycloneDX Cryptography Bill of Materials (CBOM)</title>
          <author>
            <organization>OWASP CycloneDX / Ecma International TC54</organization>
          </author>
          <date year="2025"/>
        </front>
        <refcontent>Cryptographic assets in the CycloneDX Bill of Materials
          specification (integrated in CycloneDX 1.6, extended in 1.7; published as
          Ecma International standard ECMA-424)</refcontent>
      </reference>
    </references>

    <references>
      <name>Informative References</name>

      <reference anchor="RFC9116" target="https://www.rfc-editor.org/info/rfc9116">
        <front>
          <title>A File Format to Aid in Security Vulnerability Disclosure</title>
          <author initials="E." surname="Foudil" fullname="E. Foudil"/>
          <author initials="Y." surname="Shafranovich" fullname="Y. Shafranovich"/>
          <date year="2022" month="April"/>
        </front>
        <seriesInfo name="RFC" value="9116"/>
        <seriesInfo name="DOI" value="10.17487/RFC9116"/>
      </reference>

      <reference anchor="RFC9958" target="https://www.rfc-editor.org/info/rfc9958">
        <front>
          <title>Post-Quantum Cryptography for Engineers</title>
          <author initials="A." surname="Banerjee" fullname="A. Banerjee"/>
          <author initials="T." surname="Reddy.K" fullname="T. Reddy.K"/>
          <author initials="D." surname="Schoinianakis" fullname="D. Schoinianakis"/>
          <author initials="T." surname="Hollebeek" fullname="T. Hollebeek"/>
          <author initials="M." surname="Ounsworth" fullname="M. Ounsworth"/>
          <date year="2026" month="June"/>
        </front>
        <seriesInfo name="RFC" value="9958"/>
        <seriesInfo name="DOI" value="10.17487/RFC9958"/>
      </reference>

      <reference anchor="RFC7696" target="https://www.rfc-editor.org/info/rfc7696">
        <front>
          <title>Guidelines for Cryptographic Algorithm Agility and Selecting Mandatory-to-Implement Algorithms</title>
          <author initials="R." surname="Housley" fullname="R. Housley"/>
          <date year="2015" month="November"/>
        </front>
        <seriesInfo name="BCP" value="201"/>
        <seriesInfo name="RFC" value="7696"/>
        <seriesInfo name="DOI" value="10.17487/RFC7696"/>
      </reference>

      <reference anchor="NIST-CSWP-39" target="https://doi.org/10.6028/NIST.CSWP.39">
        <front>
          <title>Considerations for Achieving Cryptographic Agility: Strategies and Practices</title>
          <author>
            <organization>National Institute of Standards and Technology</organization>
          </author>
          <date year="2025" month="December"/>
        </front>
        <seriesInfo name="NIST CSWP" value="39"/>
        <seriesInfo name="DOI" value="10.6028/NIST.CSWP.39"/>
      </reference>

      <reference anchor="NIST-SP-800-56C" target="https://doi.org/10.6028/NIST.SP.800-56Cr2">
        <front>
          <title>Recommendation for Key-Derivation Methods in Key-Establishment Schemes</title>
          <author initials="E." surname="Barker" fullname="E. Barker"/>
          <author initials="L." surname="Chen" fullname="L. Chen"/>
          <author initials="R." surname="Davis" fullname="R. Davis"/>
          <date year="2020" month="August"/>
        </front>
        <seriesInfo name="NIST SP" value="800-56C Rev. 2"/>
        <seriesInfo name="DOI" value="10.6028/NIST.SP.800-56Cr2"/>
      </reference>

      <reference anchor="NIST-IR-8547" target="https://csrc.nist.gov/pubs/ir/8547/ipd">
        <front>
          <title>Transition to Post-Quantum Cryptography Standards (Initial Public Draft)</title>
          <author>
            <organization>National Institute of Standards and Technology</organization>
          </author>
          <date year="2024" month="November"/>
        </front>
        <seriesInfo name="NIST IR" value="8547 (ipd)"/>
        <refcontent>Initial Public Draft; deprecation of quantum-vulnerable public-key
          algorithms after 2030 and disallowance after 2035</refcontent>
      </reference>

      <reference anchor="NSM-10" target="https://bidenwhitehouse.archives.gov/briefing-room/statements-releases/2022/05/04/national-security-memorandum-on-promoting-united-states-leadership-in-quantum-computing-while-mitigating-risks-to-vulnerable-cryptographic-systems/">
        <front>
          <title>National Security Memorandum on Promoting United States Leadership in Quantum Computing While Mitigating Risks to Vulnerable Cryptographic Systems (NSM-10)</title>
          <author>
            <organization>The White House</organization>
          </author>
          <date year="2022" month="May"/>
        </front>
        <refcontent>National Security Memorandum 10; goal of mitigating quantum risk to
          the maximum extent feasible by 2035</refcontent>
      </reference>

      <reference anchor="ISO-IEC-23837" target="https://www.iso.org/standard/77097.html">
        <front>
          <title>Information security - Security requirements, test and evaluation methods for quantum key distribution - Part 1: Requirements; Part 2: Evaluation and testing methods</title>
          <author>
            <organization>International Organization for Standardization / International Electrotechnical Commission</organization>
          </author>
          <date year="2023"/>
        </front>
        <seriesInfo name="ISO/IEC" value="23837-1:2023 and 23837-2:2023"/>
      </reference>
    </references>

    <section anchor="status-of-this-proposal">
      <name>Status of This Proposal</name>
      <t>
        This document is an individual Internet-Draft, the first step of the IETF process, published to solicit review. It is not the product of an IETF working group and does not represent IETF consensus, and it is not yet a standard: it is a proposal put forward to be reviewed and, if it has merit, advanced. The reference implementation, a schema, and examples are
        maintained in the open at the repository from which this draft originates.
      </t>
    </section>
  </back>

</rfc>
