<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: discernible-io</title>
    <description>The latest articles on DEV Community by discernible-io (@discernible-io).</description>
    <link>https://dev.to/discernible-io</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2685195%2F3b6a1e9f-4c9f-41a2-bda5-8a71e3072750.png</url>
      <title>DEV Community: discernible-io</title>
      <link>https://dev.to/discernible-io</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/discernible-io"/>
    <language>en</language>
    <item>
      <title>Getblock + RODiT is More</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Tue, 18 Nov 2025 07:45:34 +0000</pubDate>
      <link>https://dev.to/discernible-io/getblock-rodit-is-more-224k</link>
      <guid>https://dev.to/discernible-io/getblock-rodit-is-more-224k</guid>
      <description>&lt;p&gt;We're pleased to announce our collaboration with GetBlock.io, a leading Blockchain-as-a-Service (BaaS) platform, who is now providing RPC service sponsorship for RODiT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About GetBlock:&lt;/strong&gt;&lt;br&gt;
GetBlock.io delivers instant API access to full nodes across 50+ blockchain networks, enabling developers and businesses to build, deploy, and scale decentralized applications efficiently. Founded in 2019 and headquartered in Belgrade, Serbia, GetBlock serves thousands of developers globally with 99.9%+ uptime and 24/7 support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Matters:&lt;/strong&gt;&lt;br&gt;
RODiT provides cryptographic mutual authentication using blockchain-verified identities on NEAR Protocol. With GetBlock's reliable infrastructure, we can ensure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-availability RPC access for authentication verification&lt;/li&gt;
&lt;li&gt;Scalable infrastructure supporting our growing developer community&lt;/li&gt;
&lt;li&gt;Enterprise-grade reliability for production deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;About RODiT:&lt;/strong&gt;&lt;br&gt;
RODiT is a comprehensive authentication SDK that enables developers to implement blockchain-based mutual authentication, authorization, and session management in their applications. Our system provides cryptographic security without the complexity of managing blockchain infrastructure.&lt;/p&gt;

&lt;p&gt;This partnership allows us to focus on what we do best—building secure authentication solutions—while GetBlock handles the blockchain infrastructure layer.&lt;/p&gt;

&lt;p&gt;We're grateful to GetBlock for their support and excited about the possibilities this partnership creates for the Web3 developer community.&lt;/p&gt;

&lt;p&gt;Learn more about GetBlock: &lt;a href="https://getblock.io/about/" rel="noopener noreferrer"&gt;https://getblock.io/about/&lt;/a&gt;&lt;br&gt;
Explore GetBlock's services: &lt;a href="https://getblock.io" rel="noopener noreferrer"&gt;https://getblock.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>getblock</category>
      <category>near</category>
      <category>rodit</category>
      <category>developertools</category>
    </item>
    <item>
      <title>API keys leak. Certificates expire.</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Thu, 16 Oct 2025 12:18:39 +0000</pubDate>
      <link>https://dev.to/discernible-io/api-keys-leak-certificates-expire-25em</link>
      <guid>https://dev.to/discernible-io/api-keys-leak-certificates-expire-25em</guid>
      <description>&lt;h2&gt;
  
  
  Live Event Today: Mutual Trust, No Secrets
&lt;/h2&gt;

&lt;h3&gt;
  
  
  RODiT and the Future of API Authentication
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;📅 When:&lt;/strong&gt; Today, 3pm UTC&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🎯 What:&lt;/strong&gt; Live Q&amp;amp;A and deep dive into RODiT technology&lt;/p&gt;

&lt;p&gt;Join us as we talk with &lt;strong&gt;Discernible IO&lt;/strong&gt; about &lt;strong&gt;RODiT (Rich Online Digital Tokens)&lt;/strong&gt;, a new approach to API authentication with verifiable on-chain identities.&lt;/p&gt;

&lt;h3&gt;
  
  
  About RODiT
&lt;/h3&gt;

&lt;p&gt;Built on &lt;a href="https://near.org" rel="noopener noreferrer"&gt;@NEARProtocol&lt;/a&gt; by Discernible, RODiTs bring mutual blockchain-based trust to API authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch Live
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;NEAR DevHub&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@NEARDevHub" rel="noopener noreferrer"&gt;https://www.youtube.com/@NEARDevHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bring your questions and join the conversation!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>nearprotocol</category>
      <category>api</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Creating Debian Packages: A Quick Guide</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Thu, 02 Oct 2025 09:37:54 +0000</pubDate>
      <link>https://dev.to/discernible-io/creating-debian-packages-a-quick-guide-72n</link>
      <guid>https://dev.to/discernible-io/creating-debian-packages-a-quick-guide-72n</guid>
      <description>&lt;p&gt;Creating your own Debian packages is simpler than you might think. Here's a streamlined approach to get you started quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Setup
&lt;/h2&gt;

&lt;p&gt;First, you'll need the essential tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;build-essential devscripts debhelper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Package Structure
&lt;/h2&gt;

&lt;p&gt;Create your package directory structure. At minimum, you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;your-package/
├── debian/
│   ├── control
│   ├── changelog
│   ├── rules
│   └── compat
└── [your source files]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;debian/control&lt;/code&gt; file describes your package, &lt;code&gt;changelog&lt;/code&gt; tracks versions, &lt;code&gt;rules&lt;/code&gt; defines the build process, and &lt;code&gt;compat&lt;/code&gt; specifies the debhelper compatibility level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Package
&lt;/h2&gt;

&lt;p&gt;Once your debian directory is properly configured, building is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dpkg-buildpackage &lt;span class="nt"&gt;-us&lt;/span&gt; &lt;span class="nt"&gt;-uc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-us -uc&lt;/code&gt; flags skip signing the source and changes files, which is perfect for local development and testing. This command will create your &lt;code&gt;.deb&lt;/code&gt; file in the parent directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Install your package locally to test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; ../your-package_version_architecture.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the essence of it. While there are many nuances to packaging, this approach using &lt;code&gt;dpkg-buildpackage -us -uc&lt;/code&gt; provides a reliable foundation for creating functional Debian packages.&lt;/p&gt;

&lt;p&gt;For a more comprehensive guide with detailed examples, check out &lt;a href="https://benjamintoll.com/2023/06/21/on-creating-deb-packages/" rel="noopener noreferrer"&gt;this excellent tutorial on creating deb packages&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>debian</category>
    </item>
    <item>
      <title>RODiT Metadata Guide</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Fri, 29 Aug 2025 14:48:12 +0000</pubDate>
      <link>https://dev.to/discernible-io/rodit-metadata-guide-841</link>
      <guid>https://dev.to/discernible-io/rodit-metadata-guide-841</guid>
      <description>&lt;p&gt;This guide explains the RODiT &lt;code&gt;TokenMetadata&lt;/code&gt; structure and how to populate it for three profiles: root, server, and client. It also clarifies defaulting, FrontEnd/BackEnd responsibilities, and constraints.&lt;/p&gt;




&lt;h2&gt;
  
  
  TokenMetadata structure (as implemented)
&lt;/h2&gt;

&lt;p&gt;All fields are strings on-chain for robust, uniform serialization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;openapijson_url: String&lt;/code&gt; — URL to the OpenAPI (or equivalent) JSON describing the signing/API service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;not_after: String&lt;/code&gt; — Expiration date in &lt;code&gt;YYYY-MM-DD&lt;/code&gt; (use &lt;code&gt;1970-01-01&lt;/code&gt; to indicate no limit).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;not_before: String&lt;/code&gt; — Activation date in &lt;code&gt;YYYY-MM-DD&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_requests: String&lt;/code&gt; — Integer as string (0 = unlimited).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxrq_window: String&lt;/code&gt; — Integer as string representing the rate-window seconds (0 = unlimited window).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webhook_url: String&lt;/code&gt; — HTTPS endpoint to receive event callbacks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webhook_cidr: String&lt;/code&gt; — CIDR(s) allowed to deliver webhooks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;userselected_dn: String&lt;/code&gt; — Optional user-specified display name / DN.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allowed_cidr: String&lt;/code&gt; — CIDR(s) allowed for runtime usage (environment-bound).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allowed_iso3166list: String&lt;/code&gt; — JSON string, e.g. &lt;code&gt;{"allow":["WLD"]}&lt;/code&gt; indicating country policy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jwt_duration: String&lt;/code&gt; — Integer as string; JWT validity seconds (0 = unlimited).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissioned_routes: String&lt;/code&gt; — JSON string describing entity/method permissions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subjectuniqueidentifier_url: String&lt;/code&gt; — URL pointing to a stable identity/subject descriptor for the token’s subject.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;serviceprovider_id: String&lt;/code&gt; — An internal identifier string for the issuing service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;serviceprovider_signature: String&lt;/code&gt; — Issuer’s signature over fee/issuance data (details covered in a separate article).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Although numeric or JSON-like semantically, the contract stores all fields as strings. When fields carry JSON (e.g., &lt;code&gt;allowed_iso3166list&lt;/code&gt;, &lt;code&gt;permissioned_routes&lt;/code&gt;), pass a serialized JSON string.&lt;/li&gt;
&lt;li&gt;Date format is canonical &lt;code&gt;YYYY-MM-DD&lt;/code&gt;. Use UTC convention.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Profiles and recommended defaults
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Root RODiT (mint root)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Purpose: Top-level authority for a service provider; may be used as input for minting a server token.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Recommended value / rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;token_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd, &lt;code&gt;ulid()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Unique stable ID at issuance time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;openapijson_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;URL of the signing API &lt;code&gt;/api-docs&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_after&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1970-01-01&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_before&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Today (UTC).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxrq_window&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webhook_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;https://not-set.example.com/webhook&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webhook_cidr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.0.0.0/0&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userselected_dn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;Empty string &lt;code&gt;""&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_cidr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Where mint server can run, e.g. &lt;code&gt;0.0.0.0/0&lt;/code&gt; for unconstrained lab testing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_iso3166list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{"allow":["WLD"]}&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jwt_duration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;permissioned_routes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{"entities":{"name":"thing","methods":{"/crud/onemethod":"+0","/crud/anothermethod":"+0"}}}&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subjectuniqueidentifier_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;URL of signing API for mint server.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serviceprovider_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;bc=near.org;sc=20251001-rodit-org.testnet;id=&amp;lt;token_id&amp;gt;&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serviceprovider_signature&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Calculated by issuer; scheme covered separately.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2) Server RODiT (mint server)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Purpose: Server-side token, that is also used to authorize issuance/operations for client tokens.&lt;/li&gt;
&lt;li&gt;Derived from root; may use root as an input.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Recommended value / rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;token_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd, &lt;code&gt;ulid()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Unique ID generated by backend.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;openapijson_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;URL of signing API &lt;code&gt;/api-docs&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_after&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1970-01-01&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_before&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Same as root’s &lt;code&gt;not_before&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxrq_window&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; (no limit).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webhook_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;https://not-set.example.com/webhook&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webhook_cidr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.0.0.0/0&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userselected_dn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API Configuration&lt;/td&gt;
&lt;td&gt;Empty string &lt;code&gt;""&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_cidr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Where mint client can run, e.g. &lt;code&gt;0.0.0.0/0&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_iso3166list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{"allow":["WLD"]}&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jwt_duration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;3600&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;permissioned_routes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Same JSON pattern as root. Could be BackEnd in some implementations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subjectuniqueidentifier_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;URL (stable identifier for this server token’s subject).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serviceprovider_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;serviceprovider_id&lt;/code&gt; of root.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serviceprovider_signature&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Calculated by backend (root’s private context / Secret Manager).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3) Client RODiT (mint client)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Purpose: End-client/API-consumer token tied to actual API routing and limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Recommended value / rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;token_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd, &lt;code&gt;ulid()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Unique ID generated by backend.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;openapijson_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;URL &lt;code&gt;/api-docs&lt;/code&gt; of the public API.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_after&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1970-01-01&lt;/code&gt; (no limit) – has a cost if extended.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_before&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Same as server’s &lt;code&gt;not_before&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Numeric as string – has a cost.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxrq_window&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Numeric as string – has a cost.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webhook_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Defaults to &lt;code&gt;https://not-set.example.com/webhook&lt;/code&gt; if unused.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webhook_cidr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Same as server RODiT (operational delivery network).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userselected_dn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Optional label.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_cidr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Where the API will be served from (network boundary).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_iso3166list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{"allow":["WLD"]}&lt;/code&gt; unless geo-restricted.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jwt_duration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Policy-driven (e.g., &lt;code&gt;3600&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;permissioned_routes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FrontEnd&lt;/td&gt;
&lt;td&gt;Route-level permissions JSON string.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subjectuniqueidentifier_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;URL; stable subject identity (client/service).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serviceprovider_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Root token’s &lt;code&gt;serviceprovider_id&lt;/code&gt; (or derived).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serviceprovider_signature&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BackEnd&lt;/td&gt;
&lt;td&gt;Calculated by backend (Secret Manager).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cost flags (business policy):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client &lt;code&gt;not_after&lt;/code&gt;, &lt;code&gt;max_requests&lt;/code&gt;, and &lt;code&gt;maxrq_window&lt;/code&gt; may incur costs; encode as needed in fee JSON/signature (covered separately).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  JSON examples
&lt;/h2&gt;

&lt;p&gt;All examples use serialized JSON strings for JSON-carrying fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"openapijson_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://root.internal.example/api-docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"not_after"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1970-01-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"not_before"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-08-29"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxrq_window"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhook_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://not-set.example.com/webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhook_cidr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userselected_dn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_cidr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_iso3166list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;WLD&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jwt_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissioned_routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;entities&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;methods&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/crud/onemethod&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;+0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/crud/anothermethod&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;+0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subjectuniqueidentifier_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://root.internal.example/subject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serviceprovider_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bc=near.org;sc=20251001-rodit-org.testnet;id=&amp;lt;ROOT_TOKEN_ID&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serviceprovider_signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;signature&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Server example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"openapijson_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://server.internal.example/api-docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"not_after"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1970-01-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"not_before"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-08-29"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxrq_window"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhook_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://not-set.example.com/webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhook_cidr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userselected_dn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_cidr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_iso3166list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;WLD&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jwt_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3600"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissioned_routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;entities&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;methods&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/crud/onemethod&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;+0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/crud/anothermethod&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;+0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subjectuniqueidentifier_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://server.internal.example/subject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serviceprovider_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bc=near.org;sc=20251001-rodit-org.testnet;id=&amp;lt;ROOT_TOKEN_ID&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serviceprovider_signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;signature&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Client example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"openapijson_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.public.example/api-docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"not_after"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1970-01-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"not_before"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-08-29"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxrq_window"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"86400"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhook_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://not-set.example.com/webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhook_cidr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"203.0.113.0/24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userselected_dn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-client"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_cidr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"203.0.113.0/24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowed_iso3166list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;allow&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;WLD&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jwt_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3600"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissioned_routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;entities&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;methods&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/crud/onemethod&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;+0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/crud/anothermethod&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;+0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subjectuniqueidentifier_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://subjects.example/clients/123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serviceprovider_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bc=near.org;sc=20251001-rodit-org.testnet;id=&amp;lt;ROOT_OR_SERVER_TOKEN_ID&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serviceprovider_signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;signature&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Field-by-field guidance and validation tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dates&lt;/strong&gt;: use &lt;code&gt;YYYY-MM-DD&lt;/code&gt;. &lt;code&gt;1970-01-01&lt;/code&gt; is treated as “no limit” conventionally in this design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Numeric strings&lt;/strong&gt;: &lt;code&gt;max_requests&lt;/code&gt;, &lt;code&gt;maxrq_window&lt;/code&gt;, &lt;code&gt;jwt_duration&lt;/code&gt; are strings but should parse to non-negative integers. &lt;code&gt;0&lt;/code&gt; means unlimited for the first two; for &lt;code&gt;jwt_duration&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt; means unlimited validity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON-carrying strings&lt;/strong&gt;: ensure the string is valid JSON when parsed off-chain (e.g., UI and backend). Example patterns:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;allowed_iso3166list&lt;/code&gt;: &lt;code&gt;{"allow":["WLD"]}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissioned_routes&lt;/code&gt;: &lt;code&gt;{"entities":{"name":"thing","methods":{"/crud/onemethod":"+0","/crud/anothermethod":"+0"}}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;CIDRs&lt;/strong&gt;: Accept lists or a single CIDR; if multiple, standardize as comma-separated or a JSON list encoded as a string (match your FrontEnd/BackEnd convention consistently).&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;serviceprovider_id&lt;/code&gt;&lt;/strong&gt;: Recommended format: &lt;code&gt;bc=near.org;sc=&amp;lt;contract_account&amp;gt;;id=&amp;lt;token_id&amp;gt;&lt;/code&gt;. Example: &lt;code&gt;bc=near.org;sc=20251001-rodit-org.testnet;id=01J8...ULID&lt;/code&gt;.
&lt;h2&gt;
  
  
  End-to-end flow sketch&lt;/h2&gt;
&lt;/li&gt;



&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Root minted (private server). Establishes base policy and issuer identity.&lt;/li&gt;
&lt;li&gt;Server minted referencing root (private network). Tightens runtime constraints (e.g., JWT, allowed CIDR) and sets operational identity.&lt;/li&gt;
&lt;li&gt;Client minted referencing server (public Internet). Sets actual API routes, rate limits, and serving CIDR. Client-side limits may incur cost and should be reflected in the minting fee JSON.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Operational layers and responsibilities
&lt;/h2&gt;

&lt;p&gt;This section maps deployment layers to responsibilities, how they relate to Root/Server/Client profiles, where they authenticate, what they sign or mint, and their canonical endpoints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Portal Sanctum FE&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Root profile inputs (operator UI) and Portal configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User metadata&lt;/strong&gt;: FrontEnd-driven via .env and config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Signroot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Portal (configuration payloads); feeds Sanctum and Portal flows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Portal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: &lt;a href="https://testnet-serverfe.cableguard.net:6443/" rel="noopener noreferrer"&gt;https://testnet-serverfe.cableguard.net:6443/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Provides operator inputs used to construct Root RODiT TokenMetadata (e.g., openapijson_url, allowed_cidr).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Signroot&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Root RODiT ("mint root").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System metadata&lt;/strong&gt;: config (trusted settings).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Portal Sanctum FrontEnd (receives FrontEnd auth/session context).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Sanctum (root-level policy/signature) and produces issuer signatures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Nothing directly exposed beyond root issuance service; used as input to Server minting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: &lt;a href="https://dev-api.cableguard.net:8443" rel="noopener noreferrer"&gt;https://dev-api.cableguard.net:8443&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Produces serviceprovider_id and serviceprovider_signature for the Root token.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Server FE&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Server RODiT ("mint server").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User metadata&lt;/strong&gt;: FrontEnd.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Sanctum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Uses Signserver together with Portal context when needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: &lt;a href="https://testnet-serverfe.cableguard.net:2443/" rel="noopener noreferrer"&gt;https://testnet-serverfe.cableguard.net:2443/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Supplies FrontEnd values like jwt_duration, allowed_cidr, potentially permissioned_routes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Signserver&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Server RODiT issuance (backend signer).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System metadata&lt;/strong&gt;: config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Sanctum (trusted channel).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Server FrontEnd with Sanctum context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Server (executes the mint call) or assists mint pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: &lt;a href="https://dev-api.cableguard.net:8443" rel="noopener noreferrer"&gt;https://dev-api.cableguard.net:8443&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Ensures Server token inherits/aligns with Root (e.g., not_before, serviceprovider_id).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Client FE&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Client RODiT ("mint client").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User metadata&lt;/strong&gt;: FrontEnd.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Nothing; uses Signclient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: mint.APIURL:4443&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Chooses rate limits and dates that may incur costs (max_requests, maxrq_window, not_after).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Signclient&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Client RODiT issuance (backend signer).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System task&lt;/strong&gt;: Sanitize permissioned_routes against server policy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System metadata&lt;/strong&gt;: config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Signportal with Server (client issuance bundles).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Nothing (prepares signed payloads for mint).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: sign.APIURL:8443&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Enforces that permissioned_routes in the client metadata are a subset of allowed routes from the Server token/profile. Rejects unknown/unsafe routes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Signportal&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relates to&lt;/strong&gt;: Client onboarding via Portal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System metadata&lt;/strong&gt;: config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates to&lt;/strong&gt;: Portal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signs&lt;/strong&gt;: Signclient Portal (client-side flows coordinated with portal session).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mints&lt;/strong&gt;: Client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: &lt;a href="https://testnet-clientfe.cableguard.net:6443/" rel="noopener noreferrer"&gt;https://testnet-clientfe.cableguard.net:6443/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt;: Fronts the client mint UX; coordinates with Signclient and Server for policy validation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Layer-to-Token profile mapping
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Root token: produced by Signroot; configured by Portal Sanctum FrontEnd; consumed by Server FrontEnd/Signserver.&lt;/li&gt;
&lt;li&gt;Server token: produced by Signserver; configured by Server FrontEnd; consumed by Client FrontEnd/Signclient/Signportal.&lt;/li&gt;
&lt;li&gt;Client token: produced by Signportal with Server and Signclient; configured by Client FrontEnd; validated against Server policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sanitizing permissioned_routes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Client-side permissioned_routes must be intersected with Server policy before signing/minting.&lt;/li&gt;
&lt;li&gt;Recommended pipeline:

&lt;ul&gt;
&lt;li&gt;Client FrontEnd proposes routes (JSON string).&lt;/li&gt;
&lt;li&gt;Signclient parses and normalizes routes, removes disallowed entries, and reserializes to canonical JSON string (stable key order/whitespace if relevant to signatures).&lt;/li&gt;
&lt;li&gt;Signclient attaches sanitized permissioned_routes and computes serviceprovider_signature over the exact JSON used for minting.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why are everything strings?&lt;/strong&gt; Uniform serialization avoids on-chain schema migrations and simplifies strict signature verification by keeping a byte-identical representation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Contact and licensing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All rights reserved.&lt;/li&gt;
&lt;li&gt;Trials/evaluation: &lt;code&gt;rodit@rodit.org&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Next article: creating two intertwined root RODiT certificates for servers and clients.&lt;/li&gt;
&lt;li&gt;Separate article: fee/signature data format and signature generation.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rodit</category>
      <category>nearprotocol</category>
      <category>blockchain</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>The API RODiT smart contract</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Fri, 29 Aug 2025 14:27:50 +0000</pubDate>
      <link>https://dev.to/discernible-io/the-api-rodit-smart-contract-1dfp</link>
      <guid>https://dev.to/discernible-io/the-api-rodit-smart-contract-1dfp</guid>
      <description>&lt;h2&gt;
  
  
  Who
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Contract owner&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploys/initializes the contract and controls lifecycle.&lt;/li&gt;
&lt;li&gt;Admin methods in &lt;code&gt;src/lib.rs&lt;/code&gt;:&lt;/li&gt;
&lt;li&gt;Pause/resume: &lt;code&gt;pause_contract()&lt;/code&gt;, &lt;code&gt;resume_contract()&lt;/code&gt; (aliases: &lt;code&gt;pause()&lt;/code&gt;, &lt;code&gt;resume()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Upgrade controls: &lt;code&gt;propose_upgrade()&lt;/code&gt;, &lt;code&gt;cancel_upgrade()&lt;/code&gt;, &lt;code&gt;finalize_upgrade()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Signer management: &lt;code&gt;add_authorized_signer()&lt;/code&gt;, &lt;code&gt;remove_authorized_signer()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Token holders&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Own, transfer, and burn RODiT tokens.&lt;/li&gt;
&lt;li&gt;Methods: &lt;code&gt;rodit_transfer()&lt;/code&gt;, &lt;code&gt;rodit_burn()&lt;/code&gt;, views like &lt;code&gt;rodit_tokens_for_owner()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Authorized signers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keys permitted to sign fee data for minting (stored in &lt;code&gt;authorized_signers: UnorderedSet&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Integrators&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use view functions for metadata, tokens, and stats (read-only).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;A NEAR smart contract for API-access tokens with strong metadata semantics, upgrade discipline, and auditable events.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Core types&lt;/strong&gt; in &lt;code&gt;src/lib.rs&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Token&lt;/code&gt; with &lt;code&gt;owner_id: AccountId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TokenMetadata&lt;/code&gt; with API-policy fields (e.g., &lt;code&gt;openapijson_url&lt;/code&gt;, &lt;code&gt;permissioned_routes&lt;/code&gt;, &lt;code&gt;jwt_duration&lt;/code&gt;, &lt;code&gt;serviceprovider_id&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JsonToken&lt;/code&gt; view wrapper (token_id, owner_id, metadata)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RoditContractMetadata&lt;/code&gt; with embedded JSON-LD context &lt;code&gt;DID_WBA_JSON_LD&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ContractStatus&lt;/code&gt;: &lt;code&gt;Active | Paused | Upgrading&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ContractStats&lt;/code&gt;: &lt;code&gt;created_at&lt;/code&gt;, &lt;code&gt;last_updated_at&lt;/code&gt;, &lt;code&gt;total_supply&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Storage layout&lt;/strong&gt; in &lt;code&gt;src/lib.rs&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tokens_by_id: LookupMap&amp;lt;String, Token&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;token_metadata_by_id: UnorderedMap&amp;lt;String, TokenMetadata&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tokens_per_owner: LookupMap&amp;lt;AccountId, Vector&amp;lt;String&amp;gt;&amp;gt;&lt;/code&gt; (ordered per owner)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;authorized_signers: UnorderedSet&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage_deposits: LookupMap&amp;lt;AccountId, u128&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;upgrade_config: upgrade::ContractUpgrade&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Public API (selected)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mutations: &lt;code&gt;rodit_mint(...)&lt;/code&gt;, &lt;code&gt;rodit_transfer(...)&lt;/code&gt;, &lt;code&gt;rodit_burn(...)&lt;/code&gt;, &lt;code&gt;recover_token(...)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Views: &lt;code&gt;rodit_token&lt;/code&gt;, &lt;code&gt;rodit_tokens&lt;/code&gt;, &lt;code&gt;rodit_tokens_for_owner&lt;/code&gt;, &lt;code&gt;rodit_total_supply&lt;/code&gt;, &lt;code&gt;rodit_supply_for_owner&lt;/code&gt;, &lt;code&gt;rodit_tokens_filtered&lt;/code&gt;, &lt;code&gt;rodit_metadata&lt;/code&gt;, &lt;code&gt;rodit_metadata_jsonld&lt;/code&gt;, &lt;code&gt;did_wba_jsonld&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Management: pause/resume, upgrade lifecycle, signer management&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code layout&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/lib.rs&lt;/code&gt;: Main contract, state, endpoints, and views&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/events.rs&lt;/code&gt;: NEP-297-style event emitters&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/storage.rs&lt;/code&gt;: Storage and fee handling (&lt;code&gt;handle_account_fees_and_storage()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/token_validation.rs&lt;/code&gt;: Metadata validation for minting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/upgrade.rs&lt;/code&gt;: Time-locked upgrade configuration and helpers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Contract constants&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RODIT_METADATA_SPEC = "RODIT-near.org-20251001"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Issuer URL: &lt;code&gt;"20251001.rodit.org"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testnet account for examples&lt;/strong&gt;: &lt;code&gt;20251001-rodit-org.testnet&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialization&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;init(owner_id, metadata)&lt;/code&gt; sets the owner, applies default metadata (if &lt;code&gt;None&lt;/code&gt;), initializes collections, sets &lt;code&gt;status = Active&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Lifecycle&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most mutating ops require &lt;code&gt;status == Active&lt;/code&gt; (enforced by &lt;code&gt;assert_contract_active()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Owner can &lt;code&gt;pause_contract()&lt;/code&gt; and &lt;code&gt;resume_contract()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Upgrading: &lt;code&gt;propose_upgrade()&lt;/code&gt; → wait enforced delay → &lt;code&gt;finalize_upgrade()&lt;/code&gt; (only proposer), with status transitions &lt;code&gt;Active → Upgrading → Active&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Events&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emitted for mint, transfer, burn, recover, fees, and status changes via &lt;code&gt;src/events.rs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deterministic token order per owner&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tokens_per_owner&lt;/code&gt; uses &lt;code&gt;Vector&amp;lt;String&amp;gt;&lt;/code&gt; to preserve acquisition order.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;internal_add_token_to_owner()&lt;/code&gt;: prevents duplicates and uses &lt;code&gt;Vector::push&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;internal_remove_token_from_owner()&lt;/code&gt;: uses index &lt;code&gt;position()&lt;/code&gt; + &lt;code&gt;swap_remove()&lt;/code&gt; for O(1) removal.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Safety-first state changes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses checks-effects-interactions.&lt;/li&gt;
&lt;li&gt;Explicit &lt;code&gt;require!()&lt;/code&gt; messages for clear on-chain error debugging.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Upgrade discipline&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owner-only, proposer-bound finalize, enforced delay, and strict status transitions improve safety.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Semantic metadata&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON-LD vocabulary (&lt;code&gt;DID_WBA_JSON_LD&lt;/code&gt;) provides standard, machine-readable fields for API policy and auditing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minting (&lt;code&gt;rodit_mint(...)&lt;/code&gt;)&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Validates metadata via &lt;code&gt;validate_token_metadata(...)&lt;/code&gt; (&lt;code&gt;src/token_validation.rs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Ensures attached deposit equals the fee specified in &lt;code&gt;fee_data_json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Verifies &lt;code&gt;fee_signature_base64url&lt;/code&gt; using an authorized signer.&lt;/li&gt;
&lt;li&gt;Persists token + metadata, updates owner vector, updates &lt;code&gt;total_supply&lt;/code&gt; and timestamps.&lt;/li&gt;
&lt;li&gt;Computes actual storage delta with &lt;code&gt;env::storage_usage()&lt;/code&gt; and calls &lt;code&gt;handle_account_fees_and_storage(...)&lt;/code&gt; (&lt;code&gt;src/storage.rs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Emits standardized mint event.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Transfer / Burn&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rodit_transfer(...)&lt;/code&gt;: owner-only; moves token between owners’ vectors, updates token owner, emits event.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rodit_burn(...)&lt;/code&gt;: owner-only; removes token and metadata, decrements supply, emits event.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Views&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rodit_token(token_id)&lt;/code&gt;: returns &lt;code&gt;JsonToken&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rodit_tokens(from_index, limit)&lt;/code&gt;: paginates all tokens.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rodit_tokens_for_owner(account_id, from_index, limit)&lt;/code&gt;: paginates the owner’s token vector (in acquisition order).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rodit_tokens_filtered(..., service_provider_id)&lt;/code&gt;: filters by &lt;code&gt;TokenMetadata.serviceprovider_id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rodit_metadata_jsonld()&lt;/code&gt;: returns metadata as a JSON-LD document (with embedded &lt;code&gt;@context&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Upgrade protocol (&lt;code&gt;src/upgrade.rs&lt;/code&gt;)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;propose_upgrade(&amp;amp;mut self)&lt;/code&gt;: owner-only; sets status to &lt;code&gt;Upgrading&lt;/code&gt;, records proposer and timestamp, emits status event.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;finalize_upgrade(&amp;amp;mut self)&lt;/code&gt;: proposer-only; validates delay has elapsed, resets proposal metadata.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;set_upgrade_delay(new_delay)&lt;/code&gt;: min 60 seconds.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Deploy (fresh testnet account)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build the contract WASM (e.g., with &lt;code&gt;cargo near build&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Deploy code to &lt;code&gt;20251001-rodit-org.testnet&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;init&lt;/code&gt; with &lt;code&gt;{"owner_id":"20251001-rodit-org.testnet","metadata":null}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Event Schema (Exact)
&lt;/h2&gt;

&lt;p&gt;All events use this envelope (NEP-297 style), per &lt;code&gt;src/events.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;event_name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;event-specific&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_mint&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_mint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"owner_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"token_ids"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;token_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_transfer&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"old_owner_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"new_owner_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"token_ids"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;token_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"memo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;string or null&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_burn&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_burn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"owner_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"token_ids"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;token_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_recover&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_recover"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"previous_owner_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"new_owner_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"token_ids"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;token_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_storage_payment&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_storage_payment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"account_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;yoctoNEAR as string&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_contract_fee&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_contract_fee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;yoctoNEAR as string&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_provider_fee&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_provider_fee"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"provider_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account_id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;yoctoNEAR as string&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_signer_added&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_signer_added"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"public_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;hex-or-base64 string as logged&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_signer_removed&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_signer_removed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"public_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;hex-or-base64 string as logged&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rodit_status_change&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING nepXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RODIT-near.org-20251001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rodit_status_change"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Active | Paused | Upgrading"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example Testnet Commands (using &lt;code&gt;near&lt;/code&gt; CLI)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Status and stats&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;near view 20251001-rodit-org.testnet get_contract_status &lt;span class="nt"&gt;--network-id&lt;/span&gt; testnet
near view 20251001-rodit-org.testnet get_contract_stats &lt;span class="nt"&gt;--network-id&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Metadata JSON-LD&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;near view 20251001-rodit-org.testnet rodit_metadata_jsonld &lt;span class="nt"&gt;--network-id&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokens&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;near view 20251001-rodit-org.testnet rodit_tokens &lt;span class="s1"&gt;'{"from_index":"0","limit":10}'&lt;/span&gt; &lt;span class="nt"&gt;--network-id&lt;/span&gt; testnet
near view 20251001-rodit-org.testnet rodit_tokens_for_owner &lt;span class="s1"&gt;'{"account_id":"20251001-rodit-org.testnet","from_index":"0","limit":10}'&lt;/span&gt; &lt;span class="nt"&gt;--network-id&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transfer (example)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;near call 20251001-rodit-org.testnet rodit_transfer &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'{"receiver_id":"&amp;lt;RECEIVER&amp;gt;.testnet","token_id":"token-001","memo":null}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--account-id&lt;/span&gt; 20251001-rodit-org.testnet &lt;span class="nt"&gt;--network-id&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Licensing &amp;amp; Compliance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All rights reserved.
&lt;/li&gt;
&lt;li&gt;For trials/evaluation, contact: &lt;strong&gt;&lt;a href="mailto:rodit@rodit.org"&gt;rodit@rodit.org&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Next article: how to create two intertwined root RODiT certificates for servers and clients (and their relation to issuance and validation).&lt;/li&gt;
&lt;li&gt;Separate article: fee-signature generation details and best practices.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The RODiT contract provides a policy-rich token for API access on NEAR testnet with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ordered per-owner token tracking for predictable pagination&lt;/li&gt;
&lt;li&gt;Explicit lifecycle (Active/Paused/Upgrading) with upgrade safety&lt;/li&gt;
&lt;li&gt;JSON-LD-based metadata for semantic interoperability&lt;/li&gt;
&lt;li&gt;Standardized NEP-297-style event logs for observability&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rodit</category>
      <category>blockchain</category>
      <category>smartcontract</category>
      <category>nearprotocol</category>
    </item>
    <item>
      <title>Internet Trust Chains</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Thu, 28 Aug 2025 13:35:01 +0000</pubDate>
      <link>https://dev.to/discernible-io/internet-trust-chains-1b4</link>
      <guid>https://dev.to/discernible-io/internet-trust-chains-1b4</guid>
      <description>&lt;p&gt;Internet trust is built on quite shaky foundations. Moving packets around to the correct computer that controls each IP address involves often no less than 3 large complex pyramids of trust: BGP, DNS and PKI. Any crack in any of these leads to the others crumbling.&lt;/p&gt;

&lt;p&gt;Let's start with BGP, it works like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4pycypri49rngjnf8ts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4pycypri49rngjnf8ts.png" alt=" " width="571" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The DNS pyramid has the following components:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb296qy8uk68a45pgoubv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb296qy8uk68a45pgoubv.png" alt=" " width="477" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the PKI pyramid has these:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuewh0fhxau4ejlvpzbv9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuewh0fhxau4ejlvpzbv9.png" alt=" " width="674" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can compare these pyramids as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fur0pu6fafnxcamnnwjqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fur0pu6fafnxcamnnwjqb.png" alt=" " width="706" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can easily see that BGP, the foundation, has enormous gaps. By exploiting BGP it is possible to compromise both DNS and PKI, despite all the current mitigations in place.&lt;/p&gt;

&lt;p&gt;In particular, across all levels, there are significant gaps in &lt;br&gt;
Administrative Controls, with fraudulent participants obtaining approval, Real-time Validation and Revocation, which barely works at the PKI level as it can't scale, Transparency Mechanisms, as both IP and domain asset owners can't control who makes security assertions about their assets, Man in the middle attacks due to poor Authentication mechanisms, &lt;/p&gt;

&lt;p&gt;All these gaps result in poor security. For example the support for strong mutual authentication is poor, both in server-client and peer to peer applications. Deployments are complex, expensive and brittle.&lt;/p&gt;

&lt;p&gt;In the next article we will explain how RODiT technology can help overcoming many of these challenges.&lt;/p&gt;

</description>
      <category>internet</category>
      <category>trust</category>
      <category>pki</category>
      <category>dns</category>
    </item>
    <item>
      <title>The Chain of Trust in X.500 Digital Certificates: Power, Control, and Real-World Failures</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Mon, 07 Jul 2025 10:45:36 +0000</pubDate>
      <link>https://dev.to/discernible-io/-the-chain-of-trust-in-x500-digital-certificates-power-control-and-real-world-failures-2244</link>
      <guid>https://dev.to/discernible-io/-the-chain-of-trust-in-x500-digital-certificates-power-control-and-real-world-failures-2244</guid>
      <description>&lt;p&gt;Digital certificates form the backbone of modern internet security, enabling everything from secure web browsing to email encryption. At the heart of this system lies the concept of a "chain of trust" based on X.500 digital certificates. However, while this system appears robust on paper, real-world incidents reveal significant vulnerabilities and power imbalances that affect global internet security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding X.500 Digital Certificates
&lt;/h2&gt;

&lt;p&gt;X.500 digital certificates are based on the ITU-T X.509 standard, which defines the format for public key certificates. These certificates bind a public key to an identity (such as a person, organization, or device) and are digitally signed by a Certificate Authority to verify their authenticity.&lt;/p&gt;

&lt;p&gt;Each X.509 certificate contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subject information&lt;/strong&gt;: The entity being certified&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public key&lt;/strong&gt;: The cryptographic key for the certified entity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issuer information&lt;/strong&gt;: The CA that signed the certificate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Digital signature&lt;/strong&gt;: The CA's cryptographic signature&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validity period&lt;/strong&gt;: When the certificate is valid&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensions&lt;/strong&gt;: Additional information like key usage and certificate policies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Chain of Trust Explained
&lt;/h2&gt;

&lt;p&gt;The chain of trust is a hierarchical model where trust flows from a root Certificate Authority down through intermediate CAs to end-entity certificates. This creates a tree-like structure of trust relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Certificate Authorities
&lt;/h3&gt;

&lt;p&gt;At the top of the hierarchy sit &lt;strong&gt;Root CAs&lt;/strong&gt;. These are self-signed certificates that serve as the ultimate trust anchors. Root CAs are pre-installed in operating systems, browsers, and other software applications. When you see a padlock icon in your browser, it's because the certificate chain ultimately traces back to a trusted root CA.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intermediate Certificate Authorities
&lt;/h3&gt;

&lt;p&gt;Between root CAs and end-entity certificates are &lt;strong&gt;Intermediate CAs&lt;/strong&gt; (also called subordinate CAs). Root CAs typically don't issue certificates directly to end users. Instead, they issue certificates to intermediate CAs, which then issue certificates to other intermediates or directly to end entities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chain Validation Process
&lt;/h3&gt;

&lt;p&gt;When a certificate is presented, the validating software:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checks the end-entity certificate's signature against the issuing intermediate CA&lt;/li&gt;
&lt;li&gt;Validates each intermediate CA certificate up the chain&lt;/li&gt;
&lt;li&gt;Verifies that the chain terminates at a trusted root CA&lt;/li&gt;
&lt;li&gt;Confirms that all certificates in the chain are valid and not revoked&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The CA/Browser Forum: Who Holds the Power?
&lt;/h2&gt;

&lt;p&gt;The CA/Browser Forum is the industry consortium that sets standards for Certificate Authorities and web browsers. Understanding its membership structure reveals who truly controls internet certificate policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Membership Structure and Power Distribution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Certificate Authority Members&lt;/strong&gt;: The most influential CAs include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DigiCert&lt;/strong&gt;: One of the largest commercial CAs globally&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sectigo (formerly Comodo)&lt;/strong&gt;: Major commercial CA with significant market share&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GlobalSign&lt;/strong&gt;: European-based CA with worldwide operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entrust&lt;/strong&gt;: Enterprise-focused CA with government contracts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let's Encrypt (ISRG)&lt;/strong&gt;: Non-profit CA that has revolutionized certificate accessibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GoDaddy&lt;/strong&gt;: Web hosting company with substantial CA operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Browser Members&lt;/strong&gt;: The entities that ultimately enforce certificate policies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google (Chrome)&lt;/strong&gt;: Controls the largest browser market share globally&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mozilla (Firefox)&lt;/strong&gt;: Maintains independent root store policies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft (Edge/IE)&lt;/strong&gt;: Integrates with Windows certificate stores&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apple (Safari)&lt;/strong&gt;: Controls certificate policy for iOS and macOS ecosystems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Power Dynamics and Decision Making
&lt;/h3&gt;

&lt;p&gt;The Forum operates on a consensus model, but practical power is unevenly distributed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser Dominance&lt;/strong&gt;: Browsers hold ultimate veto power because they control what certificates users actually trust. Google's Chrome team, in particular, has driven major policy changes including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mandatory Certificate Transparency logging&lt;/li&gt;
&lt;li&gt;Shorter certificate lifespans&lt;/li&gt;
&lt;li&gt;Stricter validation requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Commercial CA Influence&lt;/strong&gt;: Large commercial CAs influence standards through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical expertise and implementation experience&lt;/li&gt;
&lt;li&gt;Financial resources for standards development&lt;/li&gt;
&lt;li&gt;Market relationships with enterprise customers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Voting Structure&lt;/strong&gt;: The Forum uses a two-thirds majority voting system, but browsers can effectively override decisions by changing their root store policies unilaterally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recent Power Struggles
&lt;/h3&gt;

&lt;p&gt;Several incidents illustrate the power dynamics:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symantec Distrust (2017)&lt;/strong&gt;: Google unilaterally decided to distrust Symantec certificates, forcing the CA to sell its business to DigiCert. This demonstrated browsers' ultimate authority over the certificate ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Certificate Transparency Mandate&lt;/strong&gt;: Browsers, led by Google, mandated CT logging despite resistance from some CAs concerned about operational complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Control Mechanisms: DNS-Based Certificate Authority Authorization (CAA)
&lt;/h2&gt;

&lt;p&gt;Domain holders have limited mechanisms to control which CAs can issue certificates for their domains, that unfortunately are not used much.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS CAA Records
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Certificate Authority Authorization (CAA)&lt;/strong&gt; records allow domain owners to specify which CAs are authorized to issue certificates for their domains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CAA Record Format&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issue "digicert.com"
example.com. CAA 0 iodef "mailto:security@example.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CAA Properties&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;issue&lt;/strong&gt;: Authorizes certificate issuance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;issuewild&lt;/strong&gt;: Authorizes wildcard certificate issuance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iodef&lt;/strong&gt;: Specifies contact for policy violations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DNS-Based Authentication of Named Entities (DANE)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DANE&lt;/strong&gt; uses DNS to specify which certificates or CAs are valid for a domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_443._tcp.example.com. TLSA 3 1 1 [certificate hash]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Certificate Transparency Monitoring
&lt;/h3&gt;

&lt;p&gt;Domain owners can monitor CT logs to detect unauthorized certificate issuance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Facebook Certificate Transparency Monitoring&lt;/strong&gt;: Automated detection of certificates issued for Facebook domains&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Certificate Transparency API&lt;/strong&gt;: Allows programmatic monitoring of certificate issuance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Failures: The MyEtherWallet BGP Attack
&lt;/h2&gt;

&lt;p&gt;One of the most significant examples of how certificate vulnerabilities can be exploited for cryptocurrency theft occurred in April 2018 with the MyEtherWallet attack.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack Sequence
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1: BGP Hijacking&lt;/strong&gt;&lt;br&gt;
Attackers compromised Amazon's Route 53 DNS service through BGP hijacking, redirecting DNS queries for MyEtherWallet.com to attacker-controlled servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Certificate Acquisition&lt;/strong&gt;&lt;br&gt;
The attackers obtained a valid Let's Encrypt certificate for MyEtherWallet.com by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controlling the DNS responses during Let's Encrypt's domain validation&lt;/li&gt;
&lt;li&gt;Using the DNS-01 challenge method to prove domain ownership&lt;/li&gt;
&lt;li&gt;Receiving a legitimate certificate that browsers trusted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Phishing Execution&lt;/strong&gt;&lt;br&gt;
With a valid certificate, the attackers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presented a convincing replica of MyEtherWallet&lt;/li&gt;
&lt;li&gt;Displayed the trusted padlock icon in browsers&lt;/li&gt;
&lt;li&gt;Harvested private keys from users attempting to access their wallets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Cryptocurrency Theft&lt;/strong&gt;&lt;br&gt;
The attackers used the harvested private keys to steal approximately $152,000 in cryptocurrency.&lt;/p&gt;
&lt;h3&gt;
  
  
  Technical Analysis
&lt;/h3&gt;

&lt;p&gt;This attack succeeded because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BGP lacks authentication&lt;/strong&gt;: Attackers could redirect traffic without cryptographic verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS validation vulnerability&lt;/strong&gt;: Let's Encrypt's domain validation relied on DNS, which the attackers controlled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User trust in certificates&lt;/strong&gt;: Users trusted the valid certificate without additional verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of HSTS preloading&lt;/strong&gt;: MyEtherWallet wasn't in the HSTS preload list, allowing the initial redirect&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Lessons Learned
&lt;/h3&gt;

&lt;p&gt;The MyEtherWallet attack highlighted several critical issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Certificate validation isn't sufficient&lt;/strong&gt;: Valid certificates don't guarantee legitimate websites&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS security is crucial&lt;/strong&gt;: BGP and DNS vulnerabilities can undermine certificate security&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Need for additional protections&lt;/strong&gt;: Certificate Transparency, CAA records, and HSTS provide additional layers of security&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The MCIP Initiative: Modernizing Certificate Infrastructure
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Multi-Perspective Certificate Issuance and Validation (MCIP)&lt;/strong&gt; initiative represents the latest effort to address fundamental weaknesses in certificate validation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Current Validation Problems
&lt;/h3&gt;

&lt;p&gt;Traditional certificate validation suffers from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single point of validation&lt;/strong&gt;: CAs typically validate domain control from a single network perspective&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BGP vulnerabilities&lt;/strong&gt;: Attackers can redirect validation traffic as in the MyEtherWallet case&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS poisoning&lt;/strong&gt;: Localized DNS attacks can fool validation processes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  MCIP Solution Architecture
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Multiple Validation Perspectives&lt;/strong&gt;: Instead of validating from a single location, CAs must validate domain control from multiple, geographically distributed vantage points.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation Requirements&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimum of 3 validation perspectives&lt;/li&gt;
&lt;li&gt;Perspectives must be in different network locations&lt;/li&gt;
&lt;li&gt;Majority consensus required for certificate issuance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementation Approaches&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distributed validation infrastructure&lt;/strong&gt;: CAs deploy validation servers globally&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third-party validation services&lt;/strong&gt;: Independent services provide validation perspectives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cooperative validation&lt;/strong&gt;: CAs share validation infrastructure&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Technical Implementation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DNS Validation Enhancement&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Traditional validation (vulnerable)
dig @8.8.8.8 _acme-challenge.example.com TXT

# MCIP validation (resilient)
dig @validator1.ca.com _acme-challenge.example.com TXT
dig @validator2.ca.com _acme-challenge.example.com TXT  
dig @validator3.ca.com _acme-challenge.example.com TXT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;HTTP Validation Enhancement&lt;/strong&gt;:&lt;br&gt;
Multiple perspectives attempt to retrieve validation tokens from different network locations, making BGP hijacking attacks much more difficult.&lt;/p&gt;
&lt;h3&gt;
  
  
  Industry Adoption
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Let's Encrypt Implementation&lt;/strong&gt;: Let's Encrypt has begun implementing multi-perspective validation, using multiple validation points for domain verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CA/Browser Forum Requirements&lt;/strong&gt;: The Forum is developing requirements for multi-perspective validation as part of the Baseline Requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser Support&lt;/strong&gt;: Major browsers are encouraging CA adoption of MCIP through root store policies.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Reality of PKI Failures
&lt;/h2&gt;

&lt;p&gt;Despite the theoretical benefits of PKI, real-world implementation reveals significant problems that affect users daily.&lt;/p&gt;
&lt;h3&gt;
  
  
  Certificate Expiration Incidents
&lt;/h3&gt;

&lt;p&gt;The Spotify outage mentioned in recent reports exemplifies a pervasive problem: &lt;strong&gt;certificate expiration causing service disruptions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Expiration Scenarios&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Forgotten renewals&lt;/strong&gt;: Organizations fail to track certificate expiration dates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex renewal processes&lt;/strong&gt;: Multi-step validation requirements delay renewals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordination failures&lt;/strong&gt;: Multiple teams must coordinate for certificate updates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing gaps&lt;/strong&gt;: Renewed certificates aren't properly tested before deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Impact Scale&lt;/strong&gt;: Certificate expiration affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Major websites and services&lt;/li&gt;
&lt;li&gt;Internal corporate systems&lt;/li&gt;
&lt;li&gt;API endpoints and microservices&lt;/li&gt;
&lt;li&gt;Mobile applications and IoT devices&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Historical CA Failures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DigiNotar (2011)&lt;/strong&gt;: Complete compromise of a Dutch CA led to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fraudulent certificates for major websites (Google, Facebook, Yahoo)&lt;/li&gt;
&lt;li&gt;Complete removal from all browser trust stores&lt;/li&gt;
&lt;li&gt;Bankruptcy of the CA company&lt;/li&gt;
&lt;li&gt;Demonstrated that WebTrust certification doesn't guarantee security&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Symantec Issues (2017)&lt;/strong&gt;: Improper certificate issuance practices resulted in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google's decision to distrust Symantec certificates&lt;/li&gt;
&lt;li&gt;Forced sale of Symantec's CA business to DigiCert&lt;/li&gt;
&lt;li&gt;Massive certificate replacement efforts across the internet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Comodo Attacks (2011)&lt;/strong&gt;: Attackers obtained fraudulent certificates for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gmail, Yahoo, Hotmail&lt;/li&gt;
&lt;li&gt;Skype, Mozilla, WordPress&lt;/li&gt;
&lt;li&gt;Demonstrated vulnerability of domain validation processes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The Trust Paradox
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;WebTrust Certification Limitations&lt;/strong&gt;: As noted in the DigiNotar case, WebTrust certification doesn't guarantee security. This creates a false sense of security where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certified CAs can still be compromised&lt;/li&gt;
&lt;li&gt;Audit processes may miss critical vulnerabilities&lt;/li&gt;
&lt;li&gt;Users have no way to assess actual CA security levels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Validation Inconsistencies&lt;/strong&gt;: Different CAs use different validation methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain Validation (DV)&lt;/strong&gt;: Minimal validation, only proves domain control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization Validation (OV)&lt;/strong&gt;: Verifies organization identity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extended Validation (EV)&lt;/strong&gt;: Rigorous identity verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users cannot easily determine validation levels, creating confusion about certificate trustworthiness.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mechanisms for Domain Control
&lt;/h2&gt;
&lt;h3&gt;
  
  
  DNS CAA Records in Practice
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Implementation Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issue "digicert.com"
example.com. CAA 0 issuewild ";"
example.com. CAA 0 iodef "mailto:security@example.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adoption rates&lt;/strong&gt;: Many domains don't implement CAA records&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS security&lt;/strong&gt;: CAA records are only as secure as DNS itself&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CA compliance&lt;/strong&gt;: Not all CAs properly check CAA records&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Certificate Transparency as a Control Mechanism
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Monitoring Implementation&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monitor_certificates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ct_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://crt.sh/?q={}&amp;amp;output=json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ct_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;certificates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;certificates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Certificate ID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Issuer: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;issuer_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not Before: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;not_before&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not After: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;not_after&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-World Monitoring&lt;/strong&gt;: Organizations like Facebook and Google operate sophisticated CT monitoring systems that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect unauthorized certificate issuance within minutes&lt;/li&gt;
&lt;li&gt;Automatically alert security teams&lt;/li&gt;
&lt;li&gt;Trigger incident response procedures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Warranty Problem: Who Pays When PKI Fails?
&lt;/h2&gt;

&lt;p&gt;One of the most significant issues with current PKI is the lack of meaningful warranties or liability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Certificate Authority Liability Limitations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Typical CA Terms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liability limited to certificate cost (often $0 for DV certificates)&lt;/li&gt;
&lt;li&gt;No warranties beyond technical compliance&lt;/li&gt;
&lt;li&gt;Exclusions for consequential damages&lt;/li&gt;
&lt;li&gt;Dispute resolution through arbitration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-World Impact&lt;/strong&gt;: When certificate failures cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service outages costing millions in revenue&lt;/li&gt;
&lt;li&gt;Security breaches exposing customer data&lt;/li&gt;
&lt;li&gt;Cryptocurrency theft (as in MyEtherWallet)&lt;/li&gt;
&lt;li&gt;Reputation damage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Affected parties have little recourse against CAs.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Race to the Bottom
&lt;/h3&gt;

&lt;p&gt;As Ian Grigg noted, the lack of meaningful liability creates a "race to the bottom" where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CAs compete on price rather than security&lt;/li&gt;
&lt;li&gt;Validation processes are minimized to reduce costs&lt;/li&gt;
&lt;li&gt;Security investments are seen as unnecessary expenses&lt;/li&gt;
&lt;li&gt;Market forces don't reward better security practices&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Usability Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  User Understanding
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Certificate Validation Complexity&lt;/strong&gt;: Users face challenges in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding certificate validation levels&lt;/li&gt;
&lt;li&gt;Recognizing legitimate vs. fraudulent certificates&lt;/li&gt;
&lt;li&gt;Knowing when to be concerned about certificate warnings&lt;/li&gt;
&lt;li&gt;Distinguishing between different types of certificate errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Professional Challenges&lt;/strong&gt;: Even security professionals struggle with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certificate chain validation&lt;/li&gt;
&lt;li&gt;Proper certificate deployment&lt;/li&gt;
&lt;li&gt;Understanding CA policy differences&lt;/li&gt;
&lt;li&gt;Implementing certificate monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Operational Difficulties
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Certificate Management&lt;/strong&gt;: Organizations face:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex renewal processes&lt;/li&gt;
&lt;li&gt;Coordination across multiple teams&lt;/li&gt;
&lt;li&gt;Testing and deployment challenges&lt;/li&gt;
&lt;li&gt;Inventory management for thousands of certificates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Automation Limitations&lt;/strong&gt;: While ACME has improved automation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many CAs don't support automated processes&lt;/li&gt;
&lt;li&gt;Complex validation requirements prevent automation&lt;/li&gt;
&lt;li&gt;Legacy systems can't integrate with modern certificate management&lt;/li&gt;
&lt;li&gt;Organizational processes haven't adapted to shorter certificate lifespans&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Future of Certificate Trust
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Emerging Solutions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Certificate Transparency Evolution&lt;/strong&gt;: CT is expanding beyond just logging to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time monitoring and alerting&lt;/li&gt;
&lt;li&gt;Automated response to suspicious certificates&lt;/li&gt;
&lt;li&gt;Integration with threat intelligence platforms&lt;/li&gt;
&lt;li&gt;Policy enforcement based on CT data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DANE and DNS Security&lt;/strong&gt;: Improvements in DNS security through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNSSEC adoption&lt;/li&gt;
&lt;li&gt;DNS over HTTPS (DoH) and DNS over TLS (DoT)&lt;/li&gt;
&lt;li&gt;Authenticated DNS responses&lt;/li&gt;
&lt;li&gt;Integration with certificate validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Blockchain and Distributed Trust&lt;/strong&gt;: Experimental approaches include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blockchain-based certificate authorities&lt;/li&gt;
&lt;li&gt;Distributed consensus for certificate validation&lt;/li&gt;
&lt;li&gt;Cryptocurrency-based incentive models for security&lt;/li&gt;
&lt;li&gt;Decentralized identity systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Regulatory Developments
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;European Union eIDAS Regulation&lt;/strong&gt;: New EU regulations may:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mandate specific CA security requirements&lt;/li&gt;
&lt;li&gt;Create liability frameworks for certificate failures&lt;/li&gt;
&lt;li&gt;Establish government oversight of CAs&lt;/li&gt;
&lt;li&gt;Require specific validation procedures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Industry Standards Evolution&lt;/strong&gt;: The CA/Browser Forum continues developing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shorter certificate lifespans (potentially 90 days)&lt;/li&gt;
&lt;li&gt;Stricter validation requirements&lt;/li&gt;
&lt;li&gt;Enhanced monitoring and reporting requirements&lt;/li&gt;
&lt;li&gt;Improved incident response procedures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion: The Paradox of PKI
&lt;/h2&gt;

&lt;p&gt;The Public Key Infrastructure represents both the foundation of internet security and one of its greatest vulnerabilities. While PKI enables secure communications at massive scale, it also creates systemic risks and single points of failure that affect global internet security.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fundamental Tensions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Security vs. Usability&lt;/strong&gt;: Stronger security measures often make certificates more difficult to obtain and manage, potentially driving users toward less secure alternatives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Centralization vs. Decentralization&lt;/strong&gt;: While centralized CAs provide scalability and consistency, they also create systemic risks and power imbalances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Market Forces vs. Security&lt;/strong&gt;: The competitive certificate market often rewards lower prices over better security, creating perverse incentives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Browser Power&lt;/strong&gt;: Web browsers, particularly Chrome, hold ultimate power over certificate policy, often overriding CA/Browser Forum consensus.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>x509</category>
      <category>rootca</category>
      <category>cybersecurity</category>
      <category>identity</category>
    </item>
    <item>
      <title>AI Coding Pitfalls and Solutions: A Practical Guide</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Mon, 27 Jan 2025 13:18:01 +0000</pubDate>
      <link>https://dev.to/discernible-io/ai-coding-pitfalls-and-solutions-a-practical-guide-j7b</link>
      <guid>https://dev.to/discernible-io/ai-coding-pitfalls-and-solutions-a-practical-guide-j7b</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Most developers, if not all, are using AI by now. This is helping both newbies and highly experienced professionals.&lt;/p&gt;

&lt;p&gt;Unfortunately, like any other tool, AI coding can be less than helpful. Do you recall stories about people who end up in a lake following a GPS map application blindly? Something similar happens frequently to developers while using AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Default Pessimism
&lt;/h3&gt;

&lt;p&gt;The AI not only misses the context you don't share with it, it will not ask for more context, assuming you are telling it everything that needs to be told. For example, if you don't say you have access to the production server, it will try to solve the issue assuming there isn't access.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Know-it-all Syndrome
&lt;/h3&gt;

&lt;p&gt;The AI will give you a long list of all the things you can check and all the things you can try, like it had the magical bullet for your issue. Good luck working your way through.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Just Plaster It!
&lt;/h3&gt;

&lt;p&gt;The AI knows nothing of root causes. Presented with an issue it will try to solve that one issue ONLY, without checking why the issue is there in the first place. It tries to solve symptoms, not problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Goldberg Machine Patch
&lt;/h3&gt;

&lt;p&gt;The AI tries to give you a solution that will solve this issue and any other possible ever present in any system ever, and check and log everything under the sun. The solution seems to be bulletproof at first sight, but it is so complex it creates issues on its own that may be harder to fix than the original issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Dude Comparisons
&lt;/h3&gt;

&lt;p&gt;The AI will compare what you need to compare, but will miss essential components, for example overall number of items.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions and Examples
&lt;/h2&gt;

&lt;p&gt;It is not hard to avoid these issues if you remember that you are a driver, not a passenger, in the coding process. Here are the solutions you can use to avoid each issue:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Default Pessimism - Solution
&lt;/h3&gt;

&lt;p&gt;Share most of the context, and instruct it to request more context whenever necessary. Provide working similar samples if available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bad Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How can I check if users are active in my system?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;AI's Limited Response:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_user_activity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Assumes only local database access
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_logs.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Better Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I need to check if users are active in my system. We have:
- PostgreSQL database with user_sessions table
- Access to Redis cache
- Cloudwatch logs
- User activity tracked in NewRelic
Please ask if you need more context about any of these systems.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;AI's Comprehensive Response:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_user_activity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Check Redis cache first for performance
&lt;/span&gt;    &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_activity:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Check database for recent sessions
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            SELECT last_active_at 
            FROM user_sessions 
            WHERE user_id = %s
            ORDER BY last_active_at DESC 
            LIMIT 1
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Know-it-all Syndrome - Solution
&lt;/h3&gt;

&lt;p&gt;Request the AI to take only one step at a time, checking the result of each step before proceeding with the next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bad Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My API endpoints are slow. How can I improve performance?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Better Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My /users endpoint is taking 2.5s to respond. Let's start by profiling the database queries.
Here's the current code:

def get_users():
    users = User.query.all()
    return jsonify([user.to_dict() for user in users])

What's the first step to identify the bottleneck?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Just Plaster It! - Solution
&lt;/h3&gt;

&lt;p&gt;Ask the AI to explain how that solution is going to solve the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bad Code Issue:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Original problem
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Payment failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Bad Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How do I fix this payment error?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Better Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;We're seeing payment failures in production. Here's the code:

try:
    process_payment(amount)
except Exception:
    return "Payment failed"

Before implementing a fix, can you help me understand:
1. What types of exceptions might occur here?
2. How would each exception impact our payment flow?
3. What logging would help us identify the root cause?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Goldberg Machine Patch - Solution
&lt;/h3&gt;

&lt;p&gt;Ask the AI if this is a standard, best practice way to solve the issue, and if there is a simpler solution that will solve it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Problem:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Bad Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How can I make this user save function more robust?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;AI's Overcomplicated Response:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Ultra-robust user saving with extensive validation and logging
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;transaction_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting user save operation &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Pre-save validation
&lt;/span&gt;        &lt;span class="n"&gt;validation_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate_user_schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;validation_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Schema validation failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;validation_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user.save.validation_error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validation_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Backup current state
&lt;/span&gt;        &lt;span class="n"&gt;existing_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;backup_collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_backup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;existing_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;# Complex retry logic
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;exponential_backoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Post-save validation
&lt;/span&gt;        &lt;span class="n"&gt;saved_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inserted_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;saved_user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Save verification failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="c1"&gt;# Extensive logging
&lt;/span&gt;        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User save successful &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user.save.success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inserted_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User save failed &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user.save.error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert_team&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User save failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Better Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I need to add basic error handling and validation to this user save function.
What's the minimal change that would catch common issues?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;AI's Simpler Response:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Save user with basic validation and error handling
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Missing required fields: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;DuplicateKeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User already exists: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Dude Comparisons - Solution
&lt;/h3&gt;

&lt;p&gt;Ask the AI to perform a bijective comparison of items. This guarantees each and every item is compared with a peer only once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bad Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compare these two API response formats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Better Prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you do a field-by-field comparison of these two API response formats,
ensuring every field in both formats is addressed:

Format A:
{
    "user_id": "string",
    "name": "string",
    "roles": ["string"]
}

Format B:
{
    "id": "string",
    "full_name": "string",
    "permissions": ["string"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following these guidelines and remembering that you are the driver in the development process, you can effectively leverage AI as a powerful tool while avoiding its common pitfalls. The key is to be specific, provide context, and guide the AI step-by-step towards the solution you need.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>HashiCorp Vault Setup Guide for NEAR Protocol Accounts</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Tue, 14 Jan 2025 15:41:20 +0000</pubDate>
      <link>https://dev.to/discernible-io/hashicorp-vault-setup-guide-for-near-protocol-accounts-3ade</link>
      <guid>https://dev.to/discernible-io/hashicorp-vault-setup-guide-for-near-protocol-accounts-3ade</guid>
      <description>&lt;h1&gt;
  
  
  HashiCorp Vault Setup Guide for NEAR Protocol Accounts
&lt;/h1&gt;

&lt;p&gt;This guide walks you through setting up a HashiCorp Vault server to securely store NEAR Protocol accounts. Before starting, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A server with Ubuntu/Debian&lt;/li&gt;
&lt;li&gt;Domain name configured&lt;/li&gt;
&lt;li&gt;SSL certificates ready&lt;/li&gt;
&lt;li&gt;Root or sudo access&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initial Setup and Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install Vault
&lt;/h3&gt;

&lt;p&gt;First, add the HashiCorp repository and install Vault:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add HashiCorp GPG key&lt;/span&gt;
wget &lt;span class="nt"&gt;-O-&lt;/span&gt; https://apt.releases.hashicorp.com/gpg | gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /usr/share/keyrings/hashicorp-archive-keyring.gpg

&lt;span class="c"&gt;# Add HashiCorp repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    https://apt.releases.hashicorp.com &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; main"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/hashicorp.list

&lt;span class="c"&gt;# Install Vault&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;vault
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Configure Vault Server
&lt;/h3&gt;

&lt;p&gt;Create the Vault configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/vault.d/vault.hcl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
ui = true
disable_mlock = true

storage "file" {
  path = "/opt/vault/data"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = false
  tls_cert_file = "/etc/vault.d/vault.crt"
  tls_key_file  = "/etc/vault.d/vault.key"
}

api_addr = "https://your-vault-domain:8200"
cluster_addr = "https://your-vault-domain:8201"

telemetry {
  disable_hostname = true
  prometheus_retention_time = "24h"
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. SSL/TLS Configuration
&lt;/h3&gt;

&lt;p&gt;Place your SSL certificates in &lt;code&gt;/etc/vault.d/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vault.crt&lt;/code&gt;: Your SSL certificate&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vault.key&lt;/code&gt;: Your private key&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you need to generate certificates, follow our guide on &lt;a href="https://dev.to/rodit-org/generate-your-lets-encrypt-digital-certificates-for-all-your-domains-using-apache-a13"&gt;generating Let's Encrypt certificates&lt;/a&gt;. Ensure your DNS is properly configured and your &lt;a href="https://dev.to/rodit-org/creating-a-new-developer-server-in-digital-ocean-h69"&gt;server is set up correctly&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Set File Permissions
&lt;/h3&gt;

&lt;p&gt;Configure proper ownership and permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set ownership&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;vault:vault /etc/vault.d/vault.hcl
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;vault:vault /etc/vault.d/vault.key
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;vault:vault /etc/vault.d/vault.crt

&lt;span class="c"&gt;# Set permissions&lt;/span&gt;
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;640 /etc/vault.d/vault.hcl
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;640 /etc/vault.d/vault.key
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;640 /etc/vault.d/vault.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Create Systemd Service
&lt;/h3&gt;

&lt;p&gt;Set up Vault as a system service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/systemd/system/vault.service &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
[Unit]
Description="HashiCorp Vault - A tool for managing secrets"
Documentation=https://www.vaultproject.io/docs/
Requires=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/vault.d/vault.hcl

[Service]
User=vault
Group=vault
ProtectSystem=full
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
SecureBits=keep-caps
AmbientCapabilities=CAP_IPC_LOCK
Capabilities=CAP_IPC_LOCK+ep
CapabilityBoundingSet=CAP_IPC_LOCK
NoNewPrivileges=yes
ExecStart=/usr/bin/vault server -config=/etc/vault.d/vault.hcl
ExecReload=/bin/kill --signal HUP &lt;/span&gt;&lt;span class="nv"&gt;$MAINPID&lt;/span&gt;&lt;span class="sh"&gt;
KillMode=process
KillSignal=SIGINT
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
LimitNOFILE=65536
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vault Initialization and Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6. Initialize and Unseal
&lt;/h3&gt;

&lt;p&gt;Start the Vault service and perform initial setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start Vault service&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;vault
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start vault

&lt;span class="c"&gt;# Configure Vault address&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'https://your-vault-domain:8200'&lt;/span&gt;

&lt;span class="c"&gt;# Initialize Vault&lt;/span&gt;
vault operator init

&lt;span class="c"&gt;# Unseal Vault (requires 3 of 5 keys)&lt;/span&gt;
vault operator unseal  &lt;span class="c"&gt;# First key&lt;/span&gt;
vault operator unseal  &lt;span class="c"&gt;# Second key&lt;/span&gt;
vault operator unseal  &lt;span class="c"&gt;# Third key&lt;/span&gt;

&lt;span class="c"&gt;# Verify status&lt;/span&gt;
vault status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Configure Access Policies
&lt;/h3&gt;

&lt;p&gt;Set up the following policies for different access levels:&lt;/p&gt;

&lt;h4&gt;
  
  
  Admin Policy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee &lt;/span&gt;signing-admin-policy.hcl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
path "sys/auth/*" {
  capabilities = ["create", "update", "delete", "sudo"]
}

path "sys/auth" {
  capabilities = ["read"]
}

path "auth/approle/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Operator Policy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee &lt;/span&gt;signing-operator-policy.hcl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
path "secret/data/signing-keys/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
  allowed_parameters = {
    "data" = []
    "options" = []
  }
}
path "secret/metadata/signing-keys/*" {
  capabilities = ["read", "list"]
}
path "secret/metadata/signing-keys" {
  capabilities = ["read", "list"]
}
path "secret/data/signing-keys" {
  capabilities = ["create", "read", "update", "list"]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  General Signing Policy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee &lt;/span&gt;signing-policy.hcl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
# Allow managing auth methods
path "sys/auth/*" {
  capabilities = ["create", "update", "delete", "sudo"]
}

# Allow listing auth methods
path "sys/auth" {
  capabilities = ["read"]
}

# Allow managing roles
path "auth/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

# Existing podman-keys permissions
path "secret/data/signing-keys/*" {
  capabilities = ["create", "read", "update", "delete"]
}

# Allow listing secrets
path "secret/metadata/*" {
  capabilities = ["list"]
}

# Allow managing AppRole auth configuration
path "auth/approle/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Reader Policy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee &lt;/span&gt;signing-reader-policy.hcl &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
path "secret/data/signing-keys/*" {
  capabilities = ["read"]
}
path "secret/metadata/signing-keys/*" {
  capabilities = ["read", "list"]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply all policies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault policy write signing-admin-policy signing-admin-policy.hcl
vault policy write signing-operator-policy signing-operator-policy.hcl
vault policy write signing-policy signing-policy.hcl
vault policy write signing-reader-policy signing-reader-policy.hcl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8. Enable Key-Value Store
&lt;/h3&gt;

&lt;p&gt;Enable the KV secrets engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault secrets &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret kv-v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9. Configure AppRole Authentication
&lt;/h3&gt;

&lt;p&gt;Set up authentication for automated access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enable AppRole&lt;/span&gt;
vault auth &lt;span class="nb"&gt;enable &lt;/span&gt;approle

&lt;span class="c"&gt;# Create role&lt;/span&gt;
vault write auth/approle/role/NEAR-MANAGER-ROLE &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;token_policies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"near-operator-policy"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;token_ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;token_max_ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;token_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"service"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;period&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"768h"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrieve role credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get Role ID&lt;/span&gt;
vault &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json auth/approle/role/NEAR-MANAGER-ROLE/role-id | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data.role_id'&lt;/span&gt;

&lt;span class="c"&gt;# Get Secret ID&lt;/span&gt;
vault write &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json auth/approle/role/NEAR-MANAGER-ROLE/secret-id | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data.secret_id'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  10. Store NEAR Protocol Accounts
&lt;/h3&gt;

&lt;p&gt;On each server that needs to access the Vault:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set Vault address&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'VAULT_SERVER_URL'&lt;/span&gt;

&lt;span class="c"&gt;# Configure credentials&lt;/span&gt;
&lt;span class="nv"&gt;ROLE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'your-role-id'&lt;/span&gt;
&lt;span class="nv"&gt;SECRET_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'your-secret-id'&lt;/span&gt;

&lt;span class="c"&gt;# Login&lt;/span&gt;
vault write auth/approle/login &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;role_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ROLE_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;secret_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SECRET_ID&lt;/span&gt;

&lt;span class="c"&gt;# Store NEAR account&lt;/span&gt;
vault kv put &lt;span class="nt"&gt;-mount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret near-accounts/my-account &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;account_json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@/path/to/near-credentials/mainnet/account.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unsealing Process
&lt;/h3&gt;

&lt;p&gt;The Vault uses a threshold unsealing process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires 3 of 5 keys by default&lt;/li&gt;
&lt;li&gt;Vault starts in a sealed state&lt;/li&gt;
&lt;li&gt;Cannot decrypt storage until unsealed&lt;/li&gt;
&lt;li&gt;Multiple operators must provide keys&lt;/li&gt;
&lt;li&gt;Never store unseal keys on the Vault server&lt;/li&gt;
&lt;li&gt;Unsealing required after maintenance/restarts&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vault</category>
      <category>nearprotocol</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Closing the PKIX Working Group is, apparently, not news</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Tue, 14 Jan 2025 12:23:32 +0000</pubDate>
      <link>https://dev.to/discernible-io/closing-the-pkix-working-group-is-apparently-not-news-3a3f</link>
      <guid>https://dev.to/discernible-io/closing-the-pkix-working-group-is-apparently-not-news-3a3f</guid>
      <description>&lt;p&gt;PKI is perfect, isn't it?&lt;/p&gt;

&lt;p&gt;The PKIX Working Group was of the digital certificates standards, among them X.509, that enable various applications such as secure email, web security (SSL/TLS), and digital signatures. It officially concluded its operations... more than ten years ago (31 October 2013) .. Coincidentally, more or less at the same time Bitcoin was created.&lt;/p&gt;

&lt;p&gt;The closure can only mean that PKI is perfect (many beg to disagree), or that the companies that sponsor work in PKI have zero interest in evolving the technology as their interests are well served with the current one.&lt;/p&gt;

&lt;p&gt;PKI, despite years of development and refinement still has challenges of around certificate management, trust hierarchies, and the susceptibility of certificate authorities to breaches and mismanagement.&lt;/p&gt;

&lt;p&gt;In order to manage some of the flaws in PKI, the main players created a system called Certificate Transparency (CT), a framework and set of standards aimed at tackling the vulnerabilities in the lifecycle of digital certificates used in public key infrastructures (PKI). CT provides a layer of security by enabling the detection of misissued or malicious certificates through publicly auditable logs. The core components of Certificate Transparency are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Public Logs: These are append-only logs where certificates are recorded. Each log entry is cryptographically secured to prevent tampering. Logs are operated by various organizations and are designed to be publicly accessible and verifiable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitors: Entities that observe and verify the entries in CT logs. Monitors can detect suspicious certificates and alert domain owners if an unauthorized certificate is issued for their domain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auditors: These are entities that check the consistency and integrity of CT logs. Auditors ensure that logs are functioning correctly and have not been tampered with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merkle Trees: A data structure used by CT logs to provide a cryptographic guarantee of the log's integrity. Merkle trees allow efficient and secure verification of individual log entries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CT has several flaws, among them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The reliance on a limited number of public logs. If a log operator is compromised or goes offline, it could disrupt the CT ecosystem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing and maintaining CT requires additional effort and resources from certificate authorities, website operators, and auditors. This complexity can be a barrier, particularly for smaller organizations with limited technical capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As the number of certificates grows, the size and management of CT logs can become challenging. The logs must handle large volumes of data efficiently while maintaining performance and integrity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CT alone does not solve all issues related to PKI and digital certificates. While it adds a layer of transparency and detection, it does not prevent misissuance or replace the need for robust security practices.&lt;/p&gt;

&lt;p&gt;So we are using a blockchain to mitigate the risks that arise form a system that was designed in the late 80s early 90s, with the requirement of being able to operate off-line.&lt;/p&gt;

&lt;p&gt;Why not evolve the technology and use self-issued blockchain based digitally signed tokens, and cut the middleman?&lt;/p&gt;

</description>
      <category>security</category>
      <category>cryptocurrency</category>
      <category>blockchain</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Generate your Let's Encrypt Digital Certificates for all your domains using Apache</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Mon, 13 Jan 2025 12:59:04 +0000</pubDate>
      <link>https://dev.to/discernible-io/generate-your-lets-encrypt-digital-certificates-for-all-your-domains-using-apache-a13</link>
      <guid>https://dev.to/discernible-io/generate-your-lets-encrypt-digital-certificates-for-all-your-domains-using-apache-a13</guid>
      <description>&lt;p&gt;As someone who's dealt with their fair share of digital certificate  headaches, I'm sharing a comprehensive guide to setting up and managing SSL/TLS certificates with Apache. You may actually use a different web server, but Apache seems to be the easiest way to achieve this. Once you are done, you just have to copy the generated certificates to the right directories in your web server of choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial DNS Setup
&lt;/h2&gt;

&lt;p&gt;First, ensure all your domains point to your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create A records for each domain&lt;/span&gt;
domain1.com -&amp;gt; server_ip
www.domain1.com -&amp;gt; server_ip
domain2.com -&amp;gt; server_ip
www.domain2.com -&amp;gt; server_ip
domain3.com -&amp;gt; server_ip
www.domain3.com -&amp;gt; server_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Directory Structure
&lt;/h2&gt;

&lt;p&gt;Create an organized directory structure that scales with multiple domains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create base directories&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/domains
&lt;span class="c"&gt;# Create individual domain directories&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in &lt;/span&gt;domain1.com domain2.com domain3.com&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/domains/&lt;span class="nv"&gt;$domain&lt;/span&gt;/public_html
    &lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/domains/&lt;span class="nv"&gt;$domain&lt;/span&gt;/logs
    &lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt; /var/www/domains/&lt;span class="nv"&gt;$domain&lt;/span&gt;
    &lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 755 /var/www/domains/&lt;span class="nv"&gt;$domain&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Virtual Host Configuration
&lt;/h2&gt;

&lt;p&gt;Create separate virtual host files for each domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create configuration files&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in &lt;/span&gt;domain1.com domain2.com domain3.com&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;sudo touch&lt;/span&gt; /etc/apache2/sites-available/&lt;span class="nv"&gt;$domain&lt;/span&gt;.conf
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Template for each domain's virtual host (example for domain1.com):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;VirtualHost&lt;/span&gt;&lt;span class="sr"&gt; *:80&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="nc"&gt;ServerAdmin&lt;/span&gt; webmaster@domain1.com
    &lt;span class="nc"&gt;ServerName&lt;/span&gt; domain1.com
    &lt;span class="nc"&gt;ServerAlias&lt;/span&gt; www.domain1.com
    &lt;span class="nc"&gt;DocumentRoot&lt;/span&gt; /var/www/domains/domain1.com/public_html
    &lt;span class="nc"&gt;ErrorLog&lt;/span&gt; /var/www/domains/domain1.com/logs/error.log
    &lt;span class="nc"&gt;CustomLog&lt;/span&gt; /var/www/domains/domain1.com/logs/access.log combined

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="sr"&gt; /var/www/domains/domain1.com/public_html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="ss"&gt;Indexes&lt;/span&gt; &lt;span class="ss"&gt;FollowSymLinks&lt;/span&gt;
        &lt;span class="nc"&gt;AllowOverride&lt;/span&gt; &lt;span class="ss"&gt;All&lt;/span&gt;
        &lt;span class="nc"&gt;Require&lt;/span&gt; &lt;span class="ss"&gt;all&lt;/span&gt; granted
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;VirtualHost&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Batch Certificate Management
&lt;/h2&gt;

&lt;p&gt;Here's how to efficiently manage certificates for multiple domains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Certbot&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-apache

&lt;span class="c"&gt;# Create a domains list file&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain1.com www.domain1.com"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; domains.txt
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain2.com www.domain2.com"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; domains.txt
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"domain3.com www.domain3.com"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; domains.txt

&lt;span class="c"&gt;# Obtain certificates for all domains in one command&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--apache&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;domains.txt | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automated Renewal Management
&lt;/h2&gt;

&lt;p&gt;Create a renewal management script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# /usr/local/bin/cert-renew-manager.sh&lt;/span&gt;

&lt;span class="c"&gt;# Renew all certificates&lt;/span&gt;
certbot renew

&lt;span class="c"&gt;# Check renewal status for each domain&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in &lt;/span&gt;domain1.com domain2.com domain3.com&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;cert_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/etc/letsencrypt/live/&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;/fullchain.pem"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cert_path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;expiry_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-enddate&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cert_path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Domain: &lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt; - Certificate expires: &lt;/span&gt;&lt;span class="nv"&gt;$expiry_date&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: No certificate found for &lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Batch Security Configuration
&lt;/h2&gt;

&lt;p&gt;Apply security headers to all domains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a common security configuration&lt;/span&gt;
&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apache2/conf-available/security-headers.conf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="c"&gt;# Enable for all sites&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;a2enconf security-headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monitoring and Maintenance
&lt;/h2&gt;

&lt;p&gt;Create a monitoring script for multiple domains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# /usr/local/bin/cert-monitor.sh&lt;/span&gt;

&lt;span class="nv"&gt;domains&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"domain1.com"&lt;/span&gt; &lt;span class="s2"&gt;"domain2.com"&lt;/span&gt; &lt;span class="s2"&gt;"domain3.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;notification_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"admin@yourdomain.com"&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;expiry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:443 &lt;span class="nt"&gt;-servername&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;/dev/null | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-enddate&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;expiry_epoch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$expiry&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;current_epoch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;days_left&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$expiry_epoch&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$current_epoch&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;86400&lt;/span&gt; &lt;span class="k"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$days_left&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 30 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: Certificate for &lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt; expires in &lt;/span&gt;&lt;span class="nv"&gt;$days_left&lt;/span&gt;&lt;span class="s2"&gt; days"&lt;/span&gt; | mail &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"Certificate Expiry Warning"&lt;/span&gt; &lt;span class="nv"&gt;$notification_email&lt;/span&gt;
    &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Batch Testing
&lt;/h2&gt;

&lt;p&gt;Create a comprehensive test script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# /usr/local/bin/cert-test.sh&lt;/span&gt;

&lt;span class="c"&gt;# Test Apache configuration&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apache2ctl configtest

&lt;span class="c"&gt;# Test SSL configuration for each domain&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in &lt;/span&gt;domain1.com domain2.com domain3.com&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Testing SSL configuration for &lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://&lt;span class="nv"&gt;$domain&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1
    openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:443 &lt;span class="nt"&gt;-servername&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;/dev/null | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-dates&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recovery Procedures
&lt;/h2&gt;

&lt;p&gt;Create a backup script for all certificates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# /usr/local/bin/cert-backup.sh&lt;/span&gt;

&lt;span class="nv"&gt;backup_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/root/cert-backups/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y%m%d&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$backup_dir&lt;/span&gt;

&lt;span class="c"&gt;# Backup all certificates and configurations&lt;/span&gt;
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; /etc/letsencrypt &lt;span class="nv"&gt;$backup_dir&lt;/span&gt;/
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; /etc/apache2/sites-available &lt;span class="nv"&gt;$backup_dir&lt;/span&gt;/

&lt;span class="c"&gt;# Archive the backup&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-czf&lt;/span&gt; &lt;span class="nv"&gt;$backup_dir&lt;/span&gt;.tar.gz &lt;span class="nv"&gt;$backup_dir&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nv"&gt;$backup_dir&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Managing multiple domains requires more automation and organization, but with these scripts and structures in place, you can efficiently manage dozens of domains without increasing administrative overhead. Remember to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep domain lists updated&lt;/li&gt;
&lt;li&gt;Run regular batch tests&lt;/li&gt;
&lt;li&gt;Maintain comprehensive backups&lt;/li&gt;
&lt;li&gt;Monitor all domains systematically&lt;/li&gt;
&lt;li&gt;Document any domain-specific configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach scales well whether you're managing a handful of domains or hundreds, while keeping your certificate management process clean and maintainable.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>webdev</category>
      <category>ssl</category>
    </item>
    <item>
      <title>Announcing RODiT API: Revolutionizing API Authentication</title>
      <dc:creator>discernible-io</dc:creator>
      <pubDate>Mon, 13 Jan 2025 09:39:52 +0000</pubDate>
      <link>https://dev.to/discernible-io/announcing-rodit-api-revolutionizing-api-authentication-3h3o</link>
      <guid>https://dev.to/discernible-io/announcing-rodit-api-revolutionizing-api-authentication-3h3o</guid>
      <description>&lt;p&gt;We're excited to announce the upcoming release of RODiT API, our innovative API subscription and authentication solution. Built on the foundation of Rich Online Digital Tokens (RODiT) and blockchain technology, RODiT API addresses critical challenges in API security and management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Seamless Integration&lt;/strong&gt;: Simplified API on boarding with integrated subscription and authentication via blockchain tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: Self-generated digital certificates with pinned keys, eliminating the need for traditional certificate management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutual Authentication&lt;/strong&gt;: Default mutual authentication for both API clients and servers, including web hooks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless Operations&lt;/strong&gt;: Fully stateless authentication, permissions, rate limits, and geolocation restrictions without the need for a backend database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client-Side Session Management&lt;/strong&gt;: Simplified API usage with server-side managed sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Key Management&lt;/strong&gt;: Independent encryption key pair changes among endpoints with no imposed expiration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Key Generation&lt;/strong&gt;: Increased security through locally generated keys, eliminating the need for central key management&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;RODiT API solves critical issues in API authentication and management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Synchronizes subscription, configuration, and authentication lifecycles&lt;/li&gt;
&lt;li&gt;Prevents unauthorized subscription sharing&lt;/li&gt;
&lt;li&gt;Simplifies API metering and infrastructure&lt;/li&gt;
&lt;li&gt;Offers flexible subscription models&lt;/li&gt;
&lt;li&gt;Enhances security through mutual authentication and local key generation&lt;/li&gt;
&lt;li&gt;Provides easy subscription management and potential for cross-service compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Join Our Beta Program
&lt;/h2&gt;

&lt;p&gt;We're looking for beta testers to help refine RODiT API. If you're interested in experiencing the future of API authentication and management, please email us at &lt;a href="mailto:iwantit@rodit.org"&gt;iwantit@rodit.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stay tuned for more updates as we approach the launch of RODiT API, a game-changer in API security and management.&lt;/p&gt;

</description>
      <category>api</category>
      <category>security</category>
      <category>webdev</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
