<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>OpenCerts Blog</title>
        <link>https://opencerts.io/blog</link>
        <description>OpenCerts Blog</description>
        <lastBuildDate>Tue, 17 Nov 2020 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Transcript v2.1]]></title>
            <link>https://opencerts.io/blog/2020/11/17/transcript-2.1</link>
            <guid>https://opencerts.io/blog/2020/11/17/transcript-2.1</guid>
            <pubDate>Tue, 17 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Transcript v2.1]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="transcript-v21">Transcript v2.1<a href="https://opencerts.io/blog/2020/11/17/transcript-2.1#transcript-v21" class="hash-link" aria-label="Direct link to Transcript v2.1" title="Direct link to Transcript v2.1" translate="no">​</a></h3>
<p>We added support for skills in <a href="https://schema.opencerts.io/transcripts/2.1" target="_blank" rel="noopener noreferrer" class="">the latest version of OpenCerts transcripts schema</a>. The skills will enrich your OpenCerts using the definition provided by <a href="https://www.skillsfuture.gov.sg/skills-framework" target="_blank" rel="noopener noreferrer" class="">WSG skills framework</a>. A skill looks like:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"frameworkUri"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://www.skillsfuture.sg/skills-framework"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"frameworkVersion"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"1.0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"frameworkName"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"SFw"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"sector"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Air Transport"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"category"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Aircraft Operations"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"competencyCode"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ATP-ACO-4001-1.1"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"competencyDescription"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Monitor aircraft systems, performance and external environments as well as comply with Air Traffic Control (ATC) instructions and en route navigation requirements to ensure safe and optimal flight conditions"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"competencyLevel"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Level 4"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"competencyLevelDescription"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Analyse aircraft performance through close monitoring of flight decks to ensure optimal flight conditions during cruise"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>You can add as many skills as needed. You can find a <a href="https://raw.githubusercontent.com/OpenCerts/open-certificate/master/schema/transcripts/2.1/example.json" target="_blank" rel="noopener noreferrer" class="">full example here</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-legacy-to-new-renderer">Migration legacy to new renderer<a href="https://opencerts.io/blog/2020/11/17/transcript-2.1#migration-legacy-to-new-renderer" class="hash-link" aria-label="Direct link to Migration legacy to new renderer" title="Direct link to Migration legacy to new renderer" translate="no">​</a></h3>
<p>In order to help more institution to adopt the decentralized architecture of OpenCerts v2, we have created a <a class="" href="https://opencerts.io/docs/v2/migrations/migrate_renderer">guide</a> to help early adopter to migrate from the legacy render to the decentralized renderer.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New error types for better error handling]]></title>
            <link>https://opencerts.io/blog/2020/10/08/new-error-types</link>
            <guid>https://opencerts.io/blog/2020/10/08/new-error-types</guid>
            <pubDate>Thu, 08 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[A good part of software engineering is to handle errors that arise from your application. At GovTech, we understand the importance of having good error handling practices too.]]></description>
            <content:encoded><![CDATA[<p>A good part of software engineering <a href="https://medium.com/swlh/getting-error-handling-right-9a1d39da0fa3" target="_blank" rel="noopener noreferrer" class="">is to handle errors</a> that arise from your application. At GovTech, we understand the importance of having good error handling practices too.</p>
<p>In this post, we detail some of our recent upgrades to the <a href="https://github.com/OpenCerts/verify/pull/10" target="_blank" rel="noopener noreferrer" class=""><code>opencerts-verify</code></a> library that improves the error handling coverage when attempting to verify OpenCerts or OpenAttestation documents.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="introduction">Introduction<a href="https://opencerts.io/blog/2020/10/08/new-error-types#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" translate="no">​</a></h3>
<p>In the past, <code>opencerts-verify</code> could only handle just a few types of errors. With the increasing usage of OpenCerts in recent months due to the Covid-19 pandemic, we've seen a wide variety of interesting and funky errors.</p>
<p>For example,</p>
<ul>
<li class="">Infura and Cloudflare would rate-limit you if you try to spam them through our verifier, and thus returns a HTTP 429 Too Many Requests error</li>
<li class="">Cloudflare's Ethereum Gateway would <a href="https://community.cloudflare.com/t/ethereum-gateway-random-502-error/195144" target="_blank" rel="noopener noreferrer" class="">randomly return</a> a HTTP 502 Bad Gateway error</li>
<li class="">Users will try to <em>tamper</em> with their certificate, just for the fun of it or to test our OpenCerts verifier 😉</li>
</ul>
<p>For the first two scenarios, our OpenCerts verifier would previously show that the certificate is invalid. That's because we didn't handle HTTP errors in <code>opencerts-verify</code>.</p>
<p>For the last scenario, our OpenCerts verifier didn't handle those cases properly and instead, our opencerts.io frontend verifier will say that it's <strong>(a)</strong> not issued and <strong>(b)</strong> revoked at the same time. While such a case can happen, it clearly doesn't reflect the actual error — that is, the user probably tampered with the certificate's <code>merkleRoot</code>. I'll describe more later in the <a href="https://opencerts.io/blog/2020/10/08/new-error-types#invalid_argument" class="">Invalid Argument</a> section.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-errors">New errors<a href="https://opencerts.io/blog/2020/10/08/new-error-types#new-errors" class="hash-link" aria-label="Direct link to New errors" title="Direct link to New errors" translate="no">​</a></h3>
<p>From <code>opencerts-verify</code> version <code>2.2.0</code>, we introduced the handling of these few errors and they are:</p>
<ul>
<li class=""><code>SERVER_ERROR</code></li>
<li class=""><code>INVALID_ARGUMENT</code></li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="server_error"><code>SERVER_ERROR</code><a href="https://opencerts.io/blog/2020/10/08/new-error-types#server_error" class="hash-link" aria-label="Direct link to server_error" title="Direct link to server_error" translate="no">​</a></h4>
<p>This error encompasses Ethers's <code>{ "bad response", "failed response", "missing response" }</code>.</p>
<p>To recap,</p>
<blockquote>
<p>A <code>4xx</code> code indicates an error caused by the user, whereas <code>5xx</code> codes tell the client that they did everything correctly and it's the server itself who caused the problem.</p>
</blockquote>
<p>Generally, Ethers classify both <code>4xx</code> and <code>5xx</code> errors as <code>bad response</code>.</p>
<p>(For those who're interested in how Ethers handle HTTP-related errors internally, you might want to take a look at <a href="https://github.com/ethers-io/ethers.js/blob/9640e864a68b4a9e84e820f0ceaf1eb56c66715f/packages/web/src.ts/index.ts" target="_blank" rel="noopener noreferrer" class="">this</a>.)</p>
<p>Instead of checking for Ethers <em>error messages</em> (e.g. bad response, missing response, etc.), we now group them using Ethers <em>error codes</em> (e.g. <code>SERVER_ERROR</code>) wherever possible — because there are just too many different error messages to handle.</p>
<p>Do note that error messages are NOT the same as error codes, you can think of error codes as an umbrella term for many error messages.</p>
<p>As for our decision to group both <strong>(a)</strong> user errors and <strong>(b)</strong> server errors together, that's because we don't need to have a finer level of granularity at this moment (i.e. we don't need to know that it's <code>4xx</code> vs <code>5xx</code>).</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="invalid_argument"><code>INVALID_ARGUMENT</code><a href="https://opencerts.io/blog/2020/10/08/new-error-types#invalid_argument" class="hash-link" aria-label="Direct link to invalid_argument" title="Direct link to invalid_argument" translate="no">​</a></h4>
<p>As the name suggests, the <code>INVALID_ARGUMENT</code> error means the input argument is invalid. In this case, we're referring to the merkle root.</p>
<p>Because our verifier uses the document's <code>merkleRoot</code> to check against what's stored on the Ethereum blockchain, there were cases where users have tried to mess with their certificate.</p>
<p>Below are three examples of invalid <code>merkleRoot</code>s:</p>
<ul>
<li class="">
<p><code>61dc9186345e05cc2ae53dc72af880a3b66e2fa7983feaa6254d1518540de5</code> is even length, but is not 64 characters (or 32 bytes) as required of merkle roots - Ethers returns error message <code>incorrect data length</code></p>
</li>
<li class="">
<p><code>61dc9186345e05cc2ae53dc72af880a3b66e2fa7983feaa6254d1518540de50</code> is not of a valid length - Ethers returns error message <code>hex is of odd-length</code></p>
</li>
<li class="">
<p><code>61dc9186345e05cc2ae53dc72af880a3b66e2fa7983feaa6254d1518540de50Z</code> is of valid length, BUT contains an invalid character (the <code>Z</code>) - Ethers returns error message <code>invalid hex string</code></p>
</li>
</ul>
<p>All three examples above are classified as <code>INVALID_ARGUMENT</code> from <code>opencerts-verify</code> version <code>2.2.0</code>.</p>
<p>For good measure, <code>61dc9186345e05cc2ae53dc72af880a3b66e2fa7983feaa6254d1518540de50a</code> is OK, leaving this here for an example of a valid <code>merkleRoot</code> to provide context for the three errors above.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-discussion">Further discussion<a href="https://opencerts.io/blog/2020/10/08/new-error-types#further-discussion" class="hash-link" aria-label="Direct link to Further discussion" title="Direct link to Further discussion" translate="no">​</a></h3>
<p>That's all for now!</p>
<blockquote>
<p>For any feedback, feel free to reach us out on <a href="https://github.com/OpenCerts" target="_blank" rel="noopener noreferrer" class="">GitHub</a>.</p>
</blockquote>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Multi issuers and deploy verify API]]></title>
            <link>https://opencerts.io/blog/2020/05/12/multi-issuers</link>
            <guid>https://opencerts.io/blog/2020/05/12/multi-issuers</guid>
            <pubDate>Tue, 12 May 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[As part of our efforts to ease the adoption of OpenCerts, we have worked on several items for the past weeks.]]></description>
            <content:encoded><![CDATA[<p>As part of our efforts to ease the adoption of OpenCerts, we have worked on several items for the past weeks.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="multi-issuers">Multi issuers<a href="https://opencerts.io/blog/2020/05/12/multi-issuers#multi-issuers" class="hash-link" aria-label="Direct link to Multi issuers" title="Direct link to Multi issuers" translate="no">​</a></h3>
<p>While having multiple issuers has always been available in OpenCerts, there has been no documentation on this feature, as well how it differs from single issuer documents. The use cases might be rare (for instance when there is a collaboration between multiple institutions), but now <a class="" href="https://opencerts.io/docs/multi-issuer">we got you covered</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="deploy-verify-api">Deploy verify API<a href="https://opencerts.io/blog/2020/05/12/multi-issuers#deploy-verify-api" class="hash-link" aria-label="Direct link to Deploy verify API" title="Direct link to Deploy verify API" translate="no">​</a></h3>
<p>We have been providing an <a href="https://github.com/OpenCerts/opencerts-functions" target="_blank" rel="noopener noreferrer" class="">API to verify OpenCerts document</a> for quite awhile, however we don't provide support or SLA for it. This resulted in people copying and pasting the code and then deploying it into their own infrastructure.</p>
<p>The repository already contained scripts to automatically deploy to different infrastructure, but there was another complication. The repository contains multiple functions and while you might be interested by the API to verify documents, you might not be interested in the other APIs.</p>
<p>We have worked on that and improved it:</p>
<ul>
<li class="">every API is independently deployable (including verify API)</li>
<li class="">the process is <a class="" href="https://opencerts.io/docs/api/verify#deployment">documented</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-from-v1-to-v2">Migration from v1 to v2<a href="https://opencerts.io/blog/2020/05/12/multi-issuers#migration-from-v1-to-v2" class="hash-link" aria-label="Direct link to Migration from v1 to v2" title="Direct link to Migration from v1 to v2" translate="no">​</a></h3>
<p>When revamping the documentation, we missed the article that covered the migration from v1 to v2. We fixed that problem, and <a class="" href="https://opencerts.io/docs/v2/migrations/v1_to_v2">the documentation is available again</a></p>
<blockquote>
<p>For any feedback, feel free to reach us out on <a href="https://github.com/OpenCerts" target="_blank" rel="noopener noreferrer" class="">Github</a>.</p>
</blockquote>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OpenCerts New Documentation]]></title>
            <link>https://opencerts.io/blog/2020/03/13/new-doc</link>
            <guid>https://opencerts.io/blog/2020/03/13/new-doc</guid>
            <pubDate>Fri, 13 Mar 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[🎉 Welcome to the brand new OpenCerts documentation 🎉]]></description>
            <content:encoded><![CDATA[<blockquote>
  <h3 class="center">🎉 Welcome to the brand new OpenCerts documentation 🎉</h3>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-organisation">Documentation organisation<a href="https://opencerts.io/blog/2020/03/13/new-doc#documentation-organisation" class="hash-link" aria-label="Direct link to Documentation organisation" title="Direct link to Documentation organisation" translate="no">​</a></h2>
<p>We have worked on revamping the documentation to make a clear distinction between OpenAttestation documentation and OpenCerts documentation.</p>
<p>One might be confuse to understand the difference between OpenAttestation and OpenCerts:</p>
<ul>
<li class="">OpenAttestation is a standard that helps to create Verifiable Document.</li>
<li class="">OpenCerts is a specific implementation, using OpenAttestation, whose purpose is to provide institutions a way to create Verifiable Certificates.</li>
</ul>
<p>In OpenCerts documentation we will then focus only on what's specific to OpenCerts:</p>
<ul>
<li class=""><a class="" href="https://opencerts.io/docs/transcripts">How to create valid OpenCerts transcripts?</a></li>
<li class=""><a class="" href="https://opencerts.io/docs/verifier">OpenCerts verifiers.</a></li>
<li class=""><a class="" href="https://opencerts.io/docs/api/verify">OpenCerts verify API.</a></li>
<li class=""><a class="" href="https://opencerts.io/docs/api/status">Suggestion to perform live transcripts.</a></li>
</ul>
<p>Other useful links:</p>
<ul>
<li class=""><a href="http://openattestation.com/" target="_blank" rel="noopener noreferrer" class="">OpenAttestation documentation</a></li>
<li class=""><a class="" href="https://opencerts.io/docs/v1">OpenCerts Legacy documentation</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-happened-in-opencerts-recently">What happened in OpenCerts recently?<a href="https://opencerts.io/blog/2020/03/13/new-doc#what-happened-in-opencerts-recently" class="hash-link" aria-label="Direct link to What happened in OpenCerts recently?" title="Direct link to What happened in OpenCerts recently?" translate="no">​</a></h2>
<p>While we were working on the documentation, we also created many components that might be useful for OpenCerts integrators:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="openattestation-cli">OpenAttestation CLI<a href="https://opencerts.io/blog/2020/03/13/new-doc#openattestation-cli" class="hash-link" aria-label="Direct link to OpenAttestation CLI" title="Direct link to OpenAttestation CLI" translate="no">​</a></h3>
<p>We worked on <strong>OpenAttestation CLI</strong> to add a new option when wrapping documents. This option allow you to specify a URL to a custom schema to ensure the validity of the document you wrap. <a class="" href="https://opencerts.io/docs/transcripts">Read more in the documentation</a>.</p>
<p>There are 2 differences between OpenCerts CLI and OpenAttestation CLI:</p>
<ul>
<li class="">OpenAttestation CLI force you to use <code>documentStore</code> instead of <code>certificateStore</code> (don't worry they are strictly equivalent).</li>
<li class="">OpenAttestation CLI force you to provide <code>identityProof</code> using DNS-TXT record.</li>
</ul>
<blockquote>
<p>We strongly recommend and encourage to use OpenAttestation CLI in the future. OpenCerts CLI will be deprecated.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opencerts-verifier">OpenCerts verifier<a href="https://opencerts.io/blog/2020/03/13/new-doc#opencerts-verifier" class="hash-link" aria-label="Direct link to OpenCerts verifier" title="Direct link to OpenCerts verifier" translate="no">​</a></h3>
<p>OpenCerts identity verification is based on a registry maintained by SSG. Because of this, OpenCerts identity verification is not compatible with OpenAttestation identity verification.</p>
<p>To overcome this problem, we built a javascript library <code>@govtechsg/opencerts-verify</code> that check the identity over OpenCerts registry and over DNS-TXT record. <a class="" href="https://opencerts.io/docs/verifier">Read more in the documentation</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opencerts-verify-api">OpenCerts verify API<a href="https://opencerts.io/blog/2020/03/13/new-doc#opencerts-verify-api" class="hash-link" aria-label="Direct link to OpenCerts verify API" title="Direct link to OpenCerts verify API" translate="no">​</a></h3>
<p>Sometimes during development you might need to make sure a certificate that you generated is valid. While you could use <a href="https://dev.opencerts.io/" target="_blank" rel="noopener noreferrer" class="">dev.opencerts.io</a> to assert the validity of the certificate, the process is hard to automate and tedious.</p>
<p>To help you on this, we published an API that you might use to validate certificate using HTTP call. <a class="" href="https://opencerts.io/docs/api/verify">Read more in the documentation</a></p>
<blockquote>
<p>This API does not provide any guarantee for production purposes. We might work on providing a terraform module that you could use to deploy the API on your own infrastructure.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="live-transcripts">Live transcripts<a href="https://opencerts.io/blog/2020/03/13/new-doc#live-transcripts" class="hash-link" aria-label="Direct link to Live transcripts" title="Direct link to Live transcripts" translate="no">​</a></h3>
<p>For institutions that might want to provide live transcripts to their students, we wrote documentation on how they can make use of OpenAttestation Status API. The documentation is just an implementation suggestion and does not mean you <strong>MUST</strong> follow it. <a class="" href="https://opencerts.io/docs/api/status">Read more in the documentation</a></p>]]></content:encoded>
        </item>
    </channel>
</rss>