<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema
  xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://csrc.nist.gov/ns/beacon/pulse/2.0"
  elementFormDefault="qualified"
  attributeFormDefault="unqualified" version="2.0.0">
  <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="https://www.w3.org/2009/01/xml.xsd">
    <xs:annotation>
      <xs:documentation xml:lang="en-US">Import general XML schema.</xs:documentation>
    </xs:annotation>
  </xs:import>

<!--
Proposed REST calls:

Pulse at time <unixTime> (or next closest AFTER the provided <unixTime>):
    https://<server name>/<context>/beacon/2.0/pulse/time/<unixTime>

Previous Pulse (the first available Pulse prior to time <unixTime>):
    https://<server name>/<context>/beacon/2.0/pulse/time/previous/<unixTime>

Next Pulse (the first available Pulse after time <unixTime>):
    https://<server name>/<context>/beacon/2.0/pulse/time/next/<unixTime>

Latest Pulse (the last available pulse on the last chain):
    https://<server name>/<context>/beacon/2.0/pulse/last
or
    https://<server name>/<context>/beacon/2.0/chain/last/pulse/last

First pulse of Last Chain (the pulse which starts the last chain):
    https://<server name>/<context>/beacon/2.0/chain/last/pulse/1

Pulse <pulseIndex> in chain <chainIndex> (pulse number <pulseIndex> within chain number <chainIndex>; non-existing pulse with those indices results in a 404 response):
    https://<server name>/<context>/beacon/2.0/chain/<chainIndex>/pulse/<pulseIndex>

Last Pulse in chain <chainIndex> (last pulse in the chain with index <chainIndex>; if the chain is still active, it returns the latest pulse):
    https://<server name>/<context>/beacon/2.0/chain/<chainIndex>/pulse/last

where <unixTime> is the number of milliseconds since 1970-01-01T00:00:00Z.

The prior calls all return a reponse in the form:
   <response xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0">
     <pulse>...</pulse>
   </response>

   or in the case of an error:
   <response xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0">
     <error>...</error>
   </response>

If a request for a next or previous pulse results in no pulse found, a 404 response is returned.

Certificate with identifier <certificateIdentifier>:
  https://<server name>/<context>/beacon/2.0/certificate/<certificateIdentifier>
   - Returns a BASE 64 encoded RFC 5280 PKIX Certficate (PEM Format)
   - non-existent certificate identifier results in a 404 reponse

External Source Message of <sourceIdentifier>:
  https://<server name>/<context>/beacon/2.0/externalSource/<sourceIdentifier>
   - returns a MIME type text/plain document which is associated with the identifier
   - the identifier is a SHA-512 Hash of this document
   - non-existent source identifier results in a 404 response

skipList between times <startUnixTime> and <endUnixTime> (a sequence of pulses, in chronological order; in each pair of consecutive pulses, the value <outputValue> of the first appears as the value <XXXXX> of the second; the first pulse in the sequence has a timestamp exactly <startUnixTime>; the last pulse in the sequence has a timestamp exactly <endUnixTime>):
  https://<server name>/<context>/beacon/2.0/skipList/<startUnixTime>/<endUnixTime>

skipList between indices <startPulseIndex> and <endPulseIndex> within chain <chainIndex> (similar to the previous call, but where the start and end pulses are defined by their indices):
  https://<server name>/<context>/beacon/2.0/skipList/<chainIndex>/<startPulseIndex>/<endPulseIndex>

  Each skipList REST call returns a response in the form:
  <response xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0">
    <skipList>
      <pulse>...</pulse>
      <pulse type="year">...</pulse>
      <pulse type="month">...</pulse>
      <pulse type="day">...</pulse>
      <pulse type="hour">...</pulse>
      <pulse type="previous">...</pulse>
    </skipList>
  </response>

  - There is no restriction on how many of each type and it is more likely than not that there will be more than one of each type in a particular response.
  - Returns a 404 response if there does not exist a pulse for either the <startUnixTime> or the <endUnixTime>
  - If the response exceeeds a server specified threshhold, returns an error of the form:
   <response xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0">
     <error>...</error>
   </response>

Chain between times <startUnixTime> and <endUnixTime> using the previous pulse field (a sequence of pulses, in chronological order); the first pulse in the sequence has a timestamp exactly <startUnixTime>; the last pulse in the sequence has a timestamp exactly <endUnixTime>):

https://<server name>/<context>/beacon/2.0/chain/time/<startUnixTime>/<endUnixTime>/previous

- Returns a response in the form:
  <response xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0">
    <skipList>
      <pulse>...</pulse>
      <pulse type="<type>">...</pulse>
      ...
      <pulse type="<type>">...</pulse>
    </skipList>
  </response>

  - Returns a 404 response if there does not exist a pulse for either the <startUnixTime> or the <endUnixTime>.
  - If the response exceeeds a server specified threshold, returns an error of the form:
   <response xmlns="http://csrc.nist.gov/ns/beacon/pulse/2.0">
     <error>...</error>
   </response>
-->

  <xs:element name="response">
    <xs:complexType>
      <xs:choice>
        <xs:element name="error" type="errorType">
          <xs:annotation>
            <xs:documentation xml:lang="en-US">An error element containing information about the error.</xs:documentation>
          </xs:annotation>
        </xs:element>
        <xs:element name="pulse" type="pulseType" minOccurs="1" maxOccurs="unbounded">
          <xs:annotation>
            <xs:documentation xml:lang="en-US">A single pulse, or a set of pulses which are not directly connected (in other words not a chain or a skipList).</xs:documentation>
          </xs:annotation>
        </xs:element>
        <xs:element name="chain" type="chainType">
          <xs:annotation>
            <xs:documentation xml:lang="en-US">A sequence of pulses with none missing (all the pulses between time T1 and T2).</xs:documentation>
          </xs:annotation>
        </xs:element>
        <xs:element name="skipList" type="chainType">
          <xs:annotation>
            <xs:documentation xml:lang="en-US">A list of pulses in chronological order within a chain; the pulses in the list are chained using the field "outputValue".</xs:documentation>
          </xs:annotation>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <!-- the error type -->
  <xs:complexType name="errorType">
    <xs:annotation>
      <xs:documentation xml:lang="en-US">A type for a beacon error response.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element name="code" type="xs:int">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">A short error code.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="description" minOccurs="1" maxOccurs="unbounded">
        <xs:complexType>
          <xs:annotation>
            <xs:documentation xml:lang="en-US">Type for a locale specific error description.</xs:documentation>
          </xs:annotation>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute ref="xml:lang" use="required"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <!-- the pulse type -->
  <xs:complexType name="pulseType">
    <xs:annotation>
      <xs:documentation xml:lang="en-US">The type for a single pulse.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element name="uri" type="xs:anyURI">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The URI which identifies the pulse as it was originally released; May also be used to retrieve this pulse.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="version">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The version string, e.g. "0.1.0".</xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:token">
            <xs:maxLength value="32"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="cipherSuite" type="xs:int">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The cipherSuite used to identify the hash and signing algorithms. Currently defined value:
            0 - SHA512 hashing and RSA signatures with PKCSv1.5 padding
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="period" type="xs:int">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The time interval, in milliseconds, between expected pulses.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="certificateId" type="sha512HexString">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The SHA-512 hash of the X.509 ASN.1 encoding of the certificate containing the public key which can be used to verify this pulse.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="chainIndex" type="xs:long">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The index (starting with one) of the chain that a pulse is contained in.</xs:documentation>
        </xs:annotation>
      </xs:element>      
      <xs:element name="pulseIndex" type="xs:long">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">A positive integer, equal to 1 for the first pulse in a chain, and incremented by 1 for each consecutive pulse within a chain.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="timeStamp" type="xs:dateTime">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">A time string formatted according to the rules of RFC 3339 (https://www.ietf.org/rfc/rfc3339.txt); all date/times must use UTC time denoted by 'Z' suffix with no local timezone adjustment.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="localRandomValue" type="sha512HexString">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">A random value represented as a 64-byte (512 bits) hex string.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="external" minOccurs="0">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The SHA-512 hash of a value that can be obtained externally to the Beacon, whose generation is outside the control of the operators of the beacon, and whose value is unpredictable to anyone before a specified time of its use in this field; additionally, it is desirable that these values are places on an external archive that ensures integrity and availability.</xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:sequence>
            <xs:element name="sourceId" type="sha512HexString">
              <xs:annotation>
                <xs:documentation xml:lang="en-US">The SHA-512 hash value of a description of the external source.</xs:documentation>
              </xs:annotation>
            </xs:element>
            <xs:element name="statusCode" type="xs:short">
              <xs:annotation>
                <xs:documentation xml:lang="en-US">The status code for retrieval of a value from the source.</xs:documentation>
              </xs:annotation>
            </xs:element>
            <xs:element name="value" type="sha512HexString">
              <xs:annotation>
                <xs:documentation xml:lang="en-US">A SHA-512 hash of a value as described in sourceId.</xs:documentation>
              </xs:annotation>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="listValue" minOccurs="1" maxOccurs="unbounded">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The SHA-512 hash value of a pulse represented as a 64-byte hex string.</xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="sha512HexString">
              <xs:attribute name="type" type="xs:token" use="required">
                <xs:annotation>
                  <xs:documentation xml:lang="en-US">the type of list value:
                   previous - the previous pulse value, or 0's if no such pulse exists;
                   hour - the outputValue of the first pulse of the UTC "hour" of the previous pulse, or 0's if no such pulse exists;
                   day - the outputValue of the first pulse of the UTC "day" of the previous pulse, or 0's if no such pulse exists;
                   month - the outputValue of the first pulse of the UTC "month" of the previous pulse, or 0's if no such pulse exists;
                   year - the outputValue of the first pulse of the UTC "year" of the previous pulse, or 0's if no such pulse exists.</xs:documentation>
                </xs:annotation>
              </xs:attribute>
              <xs:attribute name="uri" type="xs:anyURI" use="optional">
                <xs:annotation>
                  <xs:documentation xml:lang="en-US">The URI of the Pulse.</xs:documentation>
                </xs:annotation>
              </xs:attribute>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
      <xs:element name="precommitmentValue" type="sha512HexString" minOccurs="0">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The SHA-512 hash of the next localRandomValue (a pre-commitment) as a 64-byte hex string; this value may be all '0's if not used.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="statusCode" type="xs:int">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">The status code value:
            0 - Chain intact, values all good;
            1 - Start of a new chain of values, previous hash value will be all zeros;
            2 - Time between values is greater than the period, but the chain is still intact;
            3 - Time between values is greater than the period, the chain is intact, but the input of the prior precommitmentValue was lost.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="signatureValue">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">A big-endian hex encoded digital signature using the public key contained in certificateId computed over the SHA-512 hash of (in order):
            bytelen(uri); uri as a UTF-8 encoded sequence of bytes;
            bytelen(version); version as a UTF-8 encoded sequence of bytes;
            cipherSuite as a 4-byte big-endian integer value;
            period as a 4-byte big-endian integer value;
            length(certificateId); certificateId as a hex-decoded sequence of bytes;
            chainIndex as an 8-byte big-endian integer value;
            pulseIndex as an 8-byte big-endian integer value;
            bytelen(timestamp); timestamp as a UTF-8 encoded sequence of bytes;
            length(localRandomValue); localRandomValue as a hex-decoded sequence of bytes;
            length(external/sourceId); external/sourceId as a hex-decoded sequence of bytes;
            external/statusCode as a 4-byte big-endian integer value;
            length(external/value); external/value as a hex-decoded sequence of bytes;
            length(listValue[@type=’previous’]); listValue[@type=’previous’] as a hex-decoded sequence of bytes;
            length(listValue[@type=’hour’]); listValue[@type=’hour’] as a hex-decoded sequence of bytes;
            length(listValue[@type=’day’]); listValue[@type=’day’] as a hex-decoded sequence of bytes;
            length(listValue[@type=’month’]); listValue[@type=’month’] as a hex-decoded sequence of bytes;
            length(listValue[@type=’year’]); listValue[@type=’year’] as a hex-decoded sequence of bytes;
            length(precommitmentValue); precommitmentValue as a hex-decoded sequence of bytes;
            statusCode as a 4-byte big-endian integer value.
            Note:
            bytelen(x) returns the number of bytes in the UTF-8 encoded String x;
            length(x) returns the number of bytes after x has been hex decoded;
            the result of both bytelen(x) and length(x) are encoded as 4-byte big-endian integer values;
            different listValue types may be used, but if provided, they must be included in the hash in the order they are provided.</xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:token">
            <xs:maxLength value="8192"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="outputValue" type="sha512HexString">
        <xs:annotation>
          <xs:documentation xml:lang="en-US">A 64-byte hex string of the SHA-512 hash of the concatenation of the input into the signatureValue and the hex decoded signatureValue as a sequence of bytes concatenated in that order and then hashed.</xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <!-- the chain type -->
  <xs:complexType name="chainType">
    <xs:annotation>
      <xs:documentation xml:lang="en-US">A type for a sequence of pulses.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element name="pulse" minOccurs="1" maxOccurs="unbounded">
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base="pulseType">
              <xs:attribute name="type" type="xs:token" use="optional">
                <xs:annotation>
                  <xs:documentation xml:lang="en-US">The type of listValue; see documentation in pulseType for more information.</xs:documentation>
                </xs:annotation>
              </xs:attribute>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:simpleType name="sha512HexString">
      <xs:restriction base="xs:token">
        <xs:length value="128"/>
        <xs:pattern value="([0-9]|[a-f]|[A-F])*" />
      </xs:restriction>
  </xs:simpleType>
</xs:schema>
