<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Yuren&apos;s Blog - Tech</title><description>Writing is a form of thinking. Publishing and sharing are just byproducts. The real meaning lies in finding belonging and connections within one&apos;s own knowledge framework.</description><link>https://yurenju.blog/</link><language>en</language><item><title>The Door Opened by OpenClaw</title><link>https://yurenju.blog/en/posts/2026-02-06_the-door-opened-by-openclaw/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2026-02-06_the-door-opened-by-openclaw/</guid><pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;openclaw-logo.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;774&quot; height=&quot;427&quot; src=&quot;/_astro/openclaw-logo.DVrFFRTQ_JmPhF.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;“How is OpenClaw different from other AI bots?”&lt;/p&gt;
&lt;p&gt;To answer this question, let me start with the first thing I asked it to help with: &lt;strong&gt;finding coffee shops I’d like&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I have very specific preferences when it comes to coffee, which means I’d have to click into every single coffee shop on Google Maps, checking whether their menu lists the coffee’s origin, processing method, and so on before I could filter out the ones I’d actually enjoy. This has always been a real pain, and no other bot supported browsing store photos on Google Maps either.&lt;/p&gt;
&lt;p&gt;So after setting up OpenClaw, my first question was about nearby coffee shops. My next question was whether it could look at the shop’s interior photos or Google reviews. That’s when its response got really interesting.&lt;/p&gt;
&lt;p&gt;“Currently only returning basic information, no photos or review content.”&lt;/p&gt;
&lt;p&gt;“If you want, I can add photo and review functionality to this skill, but it’ll take a bit of time to modify the code. Should I do it?”&lt;/p&gt;
&lt;p&gt;My jaw literally dropped when I saw this reply. When I used ChatGPT or Gemini before, the room for customization was limited, and I’d never encountered a bot that could modify its own code to solve my problem. It was like watching it pick up a soldering iron, crack open its own mechanical chest, and rewire itself.&lt;/p&gt;
&lt;p&gt;After discussing it with the bot, here’s what it produced.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;bernard-cafe-scout.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;839&quot; height=&quot;1390&quot; src=&quot;/_astro/bernard-cafe-scout.CW-WyqDy_MwO64.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Coming back to the question of “how OpenClaw differs from other AI bots,” I’d say OpenClaw is like “having a software engineer as a partner, and giving them a computer.” Beyond using the existing tools on the computer to solve problems, the most important thing is that it can &lt;strong&gt;create and modify tools&lt;/strong&gt;. If its current tools can’t view Google Maps images, it simply modifies the code to add that capability.&lt;/p&gt;
&lt;p&gt;Most current AI chatbots primarily provide tools, and those tools need to be built by someone else before users can access specific services. OpenClaw, on the other hand, builds its own tools even when nobody has provided them. Even a tool like Claude Code, which can also build tools, is somewhat different — Claude Code’s purpose is to collaboratively develop software with you.&lt;/p&gt;
&lt;p&gt;OpenClaw’s purpose in building tools is to solve your problems in a more general sense.&lt;/p&gt;
&lt;p&gt;From there, I started tackling some of my other frustrations. For instance, I have a habit of reading news from various countries, but for reading speed, I usually have to find foreign news sites with Chinese versions — like The New York Times, Deutsche Welle, RFI, and so on. But with OpenClaw, I simply asked it to research which media outlets from different countries offer RSS feeds for their original-language news sites, then asked it to pick out stories I’d likely find interesting based on its understanding of me, translate them into Chinese, and produce an audio news briefing every morning. Now I can just listen to the news when I wake up.&lt;/p&gt;
&lt;p&gt;I even added a rating system so it can use my feedback to improve its news selection next time 😁&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;bernard-daily-news.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1288&quot; height=&quot;1417&quot; src=&quot;/_astro/bernard-daily-news.CXWOmuSN_Z2llxwL.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Of course, this brings us back to the elephant in the room. Is OpenClaw really that unsafe?&lt;/p&gt;
&lt;p&gt;This is easy enough to imagine. Give a software engineer a computer (even without admin privileges) and consider what they could do and how dangerous that could be. Ask your engineer friends about the silly things that happen in engineering circles — accidentally deleting databases, messing up git, nuking the root directory, and so on. This bot is capable of doing all of those things (even though the model itself has many safety measures in place).&lt;/p&gt;
&lt;p&gt;OpenClaw is roughly at that level of risk, plus the additional possibility of being hijacked through Prompt Injection to do other things. In my case, if someone injects malicious content into an RSS feed or comments, I’m not confident it can adequately defend against that kind of attack.&lt;/p&gt;
&lt;p&gt;So I’d say the security concerns are quite serious, especially if you don’t provide it with an isolated environment and instead run it on your own computer — that makes the security issues even greater.&lt;/p&gt;
&lt;p&gt;But none of this can overshadow the fact that OpenClaw is an experiment brimming with creativity and fun. If you look at how Anthropic or OpenAI conduct experiments, they’re relatively cautious, hoping to accomplish more within a controllable scope. OpenClaw takes the opposite approach: what if I give an AI bot a computer — how fun could that be?&lt;/p&gt;
&lt;p&gt;It’s like the dance of Shiva — the beginning of destruction, and also the moment of rebirth.&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>Making Claude Code Run Its Own Acceptance Tests</title><link>https://yurenju.blog/en/posts/2025-07-22_claude-acceptance-test/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2025-07-22_claude-acceptance-test/</guid><pubDate>Tue, 22 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over the past few months, I’ve been developing with Cursor and Claude Code, continuously pushing the boundaries to see what LLM assistance can achieve. Throughout this process, I’ve encountered common issues that many developers face:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Development speed is fast, but quality varies. When it works well, it’s surprisingly good; when it fails, it’s equally surprising&lt;/li&gt;
&lt;li&gt;When requirements aren’t clear enough, the LLM fills in details on its own, and these details aren’t necessarily what I want&lt;/li&gt;
&lt;li&gt;The LLM writes too fast and generates too much code, causing cognitive overload for developers who can’t help but accept everything when reviewing the content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After various experiments, from a software developer’s perspective, I’ve found a working method that suits collaboration with LLMs: returning to acceptance testing. After this extended period of AI collaboration, I’ve discovered that working with LLMs shares many similarities with working with human engineers: the clearer the requirements and the more discussion, the more likely the output will meet expectations.&lt;/p&gt;
&lt;p&gt;This made me recall the Cucumber framework and its Gherkin syntax that I learned early in my career. Cucumber is a Behavior-Driven Development (BDD) tool that uses human-readable and machine-readable documents as acceptance criteria. For example, if we’re developing a Todo application, one specification would be the ability to submit a todo item by pressing Enter. Using Gherkin syntax, we can describe it like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light vitesse-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#121212;color:#24292e;--shiki-dark:#dbd7caee; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gherkin&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;  Scenario&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt; Add todo item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;    When &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;I enter &lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;&quot;Buy milk&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt; in the input field&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;    And &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;I press the Enter key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;    Then &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;I should see &lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;&quot;Buy milk&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt; in the list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;    And &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;the input field should be cleared&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But how does this translate into executable tests? Typically, you need to write glue code to bridge the specification with the test logic:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light vitesse-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#121212;color:#24292e;--shiki-dark:#dbd7caee; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; Given&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; When&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; Then&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;@cucumber/cucumber&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; expect&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;@playwright/test&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D;--shiki-dark:#758575DD&quot;&gt;// Assume we have a page object to manipulate the browser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; page&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;When&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;I enter {string} in the input field&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E36209;--shiki-dark:#BD976A&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D;--shiki-dark:#758575DD&quot;&gt;  // Find the input field and enter text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; inputField&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; page&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;locator&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;input[type=&quot;text&quot;]&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;  await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; inputField&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;fill&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;When&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;I press the Enter key&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; ()&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D;--shiki-dark:#758575DD&quot;&gt;  // Press Enter key in the input field&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; inputField&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; page&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;locator&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;input[type=&quot;text&quot;]&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;  await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; inputField&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;press&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;Enter&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;Then&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;I should see {string} in the list&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#E36209;--shiki-dark:#BD976A&quot;&gt;expectedText&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D;--shiki-dark:#758575DD&quot;&gt;  // Verify that the todo item appears in the list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; todoItems&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; page&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;locator&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;.todo-item&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; itemTexts&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; todoItems&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;allTextContents&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;  expect&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt;itemTexts&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;toContain&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt;expectedText&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;Then&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;the input field should be cleared&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; ()&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D;--shiki-dark:#758575DD&quot;&gt;  // Verify that the input field is cleared&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; inputField&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; page&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;locator&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;input[type=&quot;text&quot;]&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#CB7676&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#BD976A&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt; inputField&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;inputValue&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;  expect&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#BD976A&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#80A665&quot;&gt;toBe&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ve used Cucumber in several side projects before, but never in production projects. The main reason is that introducing such a mechanism isn’t easy. It’s already rare for teams to accept TDD, let alone bridging specifications to automated testing.&lt;/p&gt;
&lt;p&gt;It’s also related to my frequent work in startup teams. Startups typically don’t have the luxury of time to practice the cycle planning from specification to testing.&lt;/p&gt;
&lt;p&gt;However, the biggest obstacle was writing glue code. Because it breaks down each sentence into separate actions, a single test scenario gets fragmented into many small pieces. Additionally, when writing Gherkin, you need to be very careful to write the same sentences identically for the same functionality, so they can be merged in the glue code. For example:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light vitesse-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#121212;color:#24292e;--shiki-dark:#dbd7caee; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;gherkin&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;When &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;I click the button &lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;&quot;ok&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#4D9375&quot;&gt;When &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;I go to click the button &lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;&quot;ok&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These would be split into two different test logic fragments. Remember, when doing the same thing, the descriptions must be exactly the same.&lt;/p&gt;
&lt;p&gt;In short, using Cucumber was a novel and interesting experience, but various obstacles prevented me from using it in production projects.&lt;/p&gt;
&lt;p&gt;However, things are different in the age of LLM-assisted software development, because LLMs can directly read specifications written in Gherkin and &lt;strong&gt;execute them directly without needing glue code&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Since LLMs can directly read and understand specifications, and through the Model Context Protocol (MCP), Cursor or Claude Code can directly operate browsers and mobile emulators to assist development. This means we can use Gherkin to describe the expected behavior, and the LLM can verify through MCP whether its development results pass acceptance testing.&lt;/p&gt;
&lt;p&gt;Gherkin syntax serves as an excellent bridge. It’s a standard syntax that both humans and LLMs can understand, so we can use this specification to confirm implementation details before development, and after development is complete, let the LLM read this specification and use MCP to operate browsers and mobile devices for acceptance testing. For a detailed demonstration, please watch the YouTube video below.&lt;/p&gt;
&lt;p&gt;!youtube[WvGY_Jcm_kY]&lt;/p&gt;
&lt;p&gt;This not only serves as a communication tool with LLMs, but when it discovers that acceptance conditions aren’t met, it can also observe and modify the implementation.&lt;/p&gt;
&lt;p&gt;If you’re interested, you can try it yourself on GitHub: &lt;a href=&quot;https://github.com/yurenju/llm-bdd-coding-demo&quot;&gt;yurenju/llm-bdd-coding-demo&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;bdd--tdd&quot;&gt;BDD + TDD&lt;/h2&gt;
&lt;p&gt;BDD can reduce the problem of unexpected results through clearer specifications and acceptance criteria, but it cannot solve the &lt;strong&gt;cognitive overload&lt;/strong&gt; problem for developers. Combining it with incremental TDD can alleviate this issue.&lt;/p&gt;
&lt;p&gt;When using BDD, development specifications and acceptance criteria can be well defined, but another situation frequently encountered in LLM development is that the LLM writes too fast. When the amount of content generated at once exceeds my cognitive capacity, I can’t resist the temptation to directly press &lt;strong&gt;confirm&lt;/strong&gt;, but sometimes not looking carefully results in content that’s not what I wanted.&lt;/p&gt;
&lt;p&gt;To solve this cognitive load, I’ve recently been testing BDD + TDD. The BDD part uses Gherkin as acceptance criteria as described earlier. But I ask the LLM to break down components, and when developing each component, follow this sequence:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First write the interface, empty classes, or empty functions, and throw an unimplemented error like &lt;code&gt;throw new Error(&apos;not implemented yet&apos;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ask it to &lt;strong&gt;write only test descriptions&lt;/strong&gt;, meaning the automated test’s &lt;code&gt;describe(&apos;description&apos;)&lt;/code&gt; and &lt;code&gt;it(&apos;description&apos;)&lt;/code&gt;, and let me review them without implementing any test logic&lt;/li&gt;
&lt;li&gt;At this stage, I’ll know roughly what level of testing it intends to write, and I can communicate directly about the granularity of tests. Usually, I significantly reduce the test items because generally, it writes too detailed&lt;/li&gt;
&lt;li&gt;After confirming the test items, ask it to write the test logic&lt;/li&gt;
&lt;li&gt;Run the tests. At this point, all newly added tests should fail (red phase)&lt;/li&gt;
&lt;li&gt;Ask it to start implementing, and run tests after implementation. Theoretically, all the tests we wrote should pass (green phase)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Under this development flow, the output of each stage stays within my cognitive capacity, and I can properly review its output. Then, after having a clear understanding of “what is correct,” like the BDD flow, it can perform well with clear completion conditions.&lt;/p&gt;
&lt;p&gt;If you’re interested in this type of development flow, you can refer to my previous work &lt;a href=&quot;https://github.com/yurenju/cursor-tdd-rules&quot;&gt;yurenju/cursor-tdd-rules&lt;/a&gt;. If you need to use it with Claude Code, some modifications will be required.&lt;/p&gt;
&lt;p&gt;However, please remember that these are still evolving collaborative development methods. Tools and usage techniques are updating very quickly, and they may soon become outdated.&lt;/p&gt;
&lt;p&gt;The main purpose of using this development method is to reduce my own cognitive burden, allowing projects to remain under my control while using LLMs as much as possible to accomplish my goals. At the same time, by defining boundaries and goals, I can better communicate with the LLM about what my objectives actually are.&lt;/p&gt;
&lt;p&gt;Through this process, I also feel that I become clearer about what I want from the early stages of development. The key to working with LLMs is similar to working with humans: more frequent communication and requirement confirmation.&lt;/p&gt;
&lt;p&gt;So perhaps it’s not that different from working with humans after all - it’s about strengthening your communication skills.&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>Asked AI to Write Code, But It Can&apos;t Understand Me?</title><link>https://yurenju.blog/en/posts/2025-04-23_ai-coding-doesnt-understand-me/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2025-04-23_ai-coding-doesnt-understand-me/</guid><pubDate>Wed, 23 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, one of the sub-projects in our company’s new project experimented with a new development approach: attempting to write most of the code using AI (Cursor), minimizing human intervention as much as possible, hoping to understand the future software development model through small-scale experimentation.&lt;/p&gt;
&lt;p&gt;We also hoped that with AI’s assistance, we could significantly shorten the development cycle:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;reduce-development-cycle.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;952&quot; height=&quot;620&quot; src=&quot;/_astro/reduce-development-cycle.DfsiRO6k_4RYfV.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;If you’ve tried this on a slightly larger project, you can probably guess what our initial results were like:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;expected-and-actual.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;952&quot; height=&quot;620&quot; src=&quot;/_astro/expected-and-actual.DN7tC4id_G5Qat.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Whenever we wanted AI to do a bit more, it often couldn’t follow our expectations. Most work that can be completed in one go is usually simple, clear, and unambiguous tasks—these are usually done well.&lt;/p&gt;
&lt;p&gt;Of course, we won’t stop using AI for development because of this. For me personally, over 80-90% of the code is now developed using AI, with extensive use of conversational development. Since AI has deep software development capabilities, I can seriously act as a supervisor, ensuring that its work is completed as expected.&lt;/p&gt;
&lt;p&gt;But how do we reach this level? Before actually introducing AI to a project, we need to reflect on how we usually develop software projects within the team.&lt;/p&gt;
&lt;h2 id=&quot;traditional-software-development-discussions&quot;&gt;Traditional Software Development Discussions&lt;/h2&gt;
&lt;p&gt;In traditional software development processes, teams often conduct strategic discussions from a product perspective, and then the engineering team discusses technical solutions. After meetings and documentation, once consensus is reached, the product is gradually developed through iterative development.&lt;/p&gt;
&lt;p&gt;What’s important in the software development process is the team’s &lt;strong&gt;consensus&lt;/strong&gt; and &lt;strong&gt;context&lt;/strong&gt;. When we expect AI to create the ideal system in our minds based on just a few words, relying on the common sense of software engineers it has learned, what’s missing is conveying the most important consensus and context to it.&lt;/p&gt;
&lt;p&gt;Because it’s not a mind reader—it won’t know this context from just a few short conversations.&lt;/p&gt;
&lt;p&gt;Teams can build consensus and clarify context through meetings and documentation. So how do we provide such information to AI? There are several things we can try.&lt;/p&gt;
&lt;h2 id=&quot;use-rules-to-define-direction&quot;&gt;Use Rules to Define Direction&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;rule-for-right-track.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1904&quot; height=&quot;1241&quot; src=&quot;/_astro/rule-for-right-track.Ccz50Og7_Z11rC5v.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;In Cursor, you can define rules. Although writing quality rules still requires a lot of time to consider and refine, rules can set a general direction for AI and bring its working style closer to the team’s.&lt;/p&gt;
&lt;p&gt;For example, should we write tests? To what extent? What kind of git commit messages do we prefer? What are the component writing conventions, naming rules, and technology stack to adopt? Without communicating these, it will often do as it pleases, like a software engineer who just joined the team and hasn’t yet adapted to the development culture.&lt;/p&gt;
&lt;h2 id=&quot;break-down-specs-and-progress-step-by-step&quot;&gt;Break Down Specs and Progress Step by Step&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;rules-specs-impl.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1904&quot; height=&quot;1241&quot; src=&quot;/_astro/rules-specs-impl.DIlftk9A_6AljF.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Write a feature specification before implementation (of course, have it write it). Fully read and discuss the spec first, ensure what it wants to do is the same as what you want to do, then ask it to implement.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;rule-spec-workflow.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1904&quot; height=&quot;1241&quot; src=&quot;/_astro/rule-spec-workflow.D4vnUEhT_ZpHewc.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;You don’t have to write all the feature specs yourself. In our case, usually after creating a task in a project management service (like Asana), I tell it what I know this task should do, and ask it to write the spec. Then we discuss and update the spec it produced, and after completing the spec, open a new Chat Context and ask it to implement according to the spec.&lt;/p&gt;
&lt;p&gt;If you feel the spec isn’t written well, then revise the rule that generates the spec so that the team can generate better documentation quality when creating specs in the future.&lt;/p&gt;
&lt;p&gt;The length of specs will vary depending on team habits, but shorter ones are easier to read and make it easier to develop according to our intentions. This helps us better achieve our goals.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;feature-specs.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1904&quot; height=&quot;1241&quot; src=&quot;/_astro/feature-specs.C9NK3AYu_Z1e9vYV.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;As mentioned earlier, without context or consensus, it’s very difficult to make the product we want. Besides establishing context and consensus through Rules, another way to avoid this problem is to set the goal first, but don’t write all the specs at once—only write the spec for the feature you’re about to complete.&lt;/p&gt;
&lt;p&gt;Since we’ll correct the direction it wants to go based on the spec it writes, each time we write and implement a spec, we can correct deviations. This allows the project to move from idea to actual product in the expected direction.&lt;/p&gt;
&lt;h2 id=&quot;specs-should-have-acceptance-criteria&quot;&gt;Specs Should Have Acceptance Criteria&lt;/h2&gt;
&lt;p&gt;The content of specs will vary with each team, but I recommend having Acceptance Criteria. These acceptance criteria explicitly tell AI what counts as done. Such clear conditions can help AI more concretely know to what extent it needs to complete something.&lt;/p&gt;
&lt;p&gt;There are many ways to define acceptance criteria. From an engineer’s perspective, automated tests or checks can be substituted, such as unit tests or integration tests. Also, if you’re developing a web application, you can use &lt;a href=&quot;https://github.com/microsoft/playwright-mcp&quot;&gt;microsoft/playwright-mcp&lt;/a&gt; to have AI open a browser to see what the current result is, and verify by directly operating the webpage.&lt;/p&gt;
&lt;p&gt;When it can better judge the current results, it becomes easier to determine completion and take subsequent actions.&lt;/p&gt;
&lt;p&gt;If automated verification isn’t possible, you can also ask it to list manual testing methods, verify them yourself, and then tell it the results. Of course, it would be better if it can verify and fix itself.&lt;/p&gt;
&lt;h2 id=&quot;so-far&quot;&gt;So Far…&lt;/h2&gt;
&lt;p&gt;We’re also still trying out this development model, and there are many things that need adjustment in this process. Currently, we feel the rules -&gt; spec -&gt; implementation workflow works reasonably well. When writing specs, there’s an opportunity to discuss with AI and update the plan, so before starting work, we can adjust it to the form we want to complete.&lt;/p&gt;
&lt;p&gt;However, we’ve also encountered the problem that Cursor isn’t very good at following rules. Over time, these issues should gradually be fixed, or better practices will accumulate. But until that day comes, we’ll likely need to frequently modify rules. Currently, we feel that rules that are too long tend to be forgotten, and clear and short ones work better. Also, the description of rules is important because it affects when AI wants to apply specific rules.&lt;/p&gt;
&lt;p&gt;Also, recently many people have been talking about Vibe Coding, which is developing through conversation in an almost intuitive way, not caring much about implementation details.&lt;/p&gt;
&lt;p&gt;But actually, a large part of what’s called “intuition” is that you already have deep background knowledge and experience in a domain, which allows you to seemingly effortlessly complete things using “intuition.” In reality, not everyone can do this, and it also involves expressive ability.&lt;/p&gt;
&lt;p&gt;To reach this level, you still need to see whether the person operating has sufficiently deep insights into the product domain and possesses sufficiently refined and clear expressive ability.&lt;/p&gt;
&lt;p&gt;I think everyone should approach from their own perspective, seeing what method suits them for collaborating with AI to develop software projects. As a software engineer and a curious person, plus having accumulated certain expressive abilities from years of writing, I adopt methods suitable for me to collaborate with AI—more precisely describing my needs, dividing work, setting acceptance criteria and software development preferences, and even using automated testing methods to enable AI to do better.&lt;/p&gt;
&lt;p&gt;I just start from my own perspective, understanding what I like and what I’m good at, then customize the workflow with AI. In this interaction, I discovered that compared to writing code, I prefer building products. Interacting with AI gives me the opportunity to separate these two things more clearly and understand myself better.&lt;/p&gt;
&lt;p&gt;And everyone is different. My advice is to look back and examine what you like and what you’re good at, then find a suitable way to collaborate with AI. There’s no shortcut to understanding yourself—everyone just has to spend a lot of time exploring.&lt;/p&gt;
&lt;p&gt;Even if your interest is writing code yourself and this process brings you happiness, then perhaps not using AI is best for you. In &lt;a href=&quot;https://www.youtube.com/watch?v=pVr3sEeus6E&amp;#x26;t=1245s&quot;&gt;Naoki Urasawa’s interview&lt;/a&gt;, he mentions his view on AI art, saying: “Because I think drawing is very enjoyable, for someone like me who can find joy in work, wouldn’t it be a waste to leave it to AI?”&lt;/p&gt;
&lt;p&gt;What the masses are pursuing isn’t necessarily what’s right for you. You still need to look back and understand what kind of person you are, what you’re passionate about, and take the next step from your own perspective.&lt;/p&gt;
&lt;p&gt;It’s okay if AI can’t understand what you’re saying. Understanding yourself is more important.&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>Trading Tokens Directly Within Claude Desktop</title><link>https://yurenju.blog/en/posts/2025-03-13_uniswap-mcp/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2025-03-13_uniswap-mcp/</guid><pubDate>Thu, 13 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Conversational AI tools initially had no access to external information, but gradually began to integrate external tools such as search functionality. However, “search” is a broad and expansive feature. For specific functions like checking the weather or querying stock prices, while web search can accomplish these tasks, it still falls short compared to directly integrating new weather or stock market features through APIs.&lt;/p&gt;
&lt;p&gt;Looking at the broader picture, there are countless services on the internet, making it impossible to connect them all through APIs. Moreover, some tools are not in HTTP API format but are only available on local computers. For example, when programming, it would be ideal for an editor to access precise browser screens, structures, and developer debugging information, which cannot be connected through HTTP APIs.&lt;/p&gt;
&lt;p&gt;MCP is an open standard designed to help AI understand how to utilize tools. For instance, if you want assistance with task management, you can use an Asana MCP to connect to a task management service via API, enabling it to help plan entire projects, create necessary data, and even manage task dependencies.&lt;/p&gt;
&lt;p&gt;The browser-assisted development mentioned earlier can also be achieved through &lt;a href=&quot;https://github.com/executeautomation/mcp-playwright&quot;&gt;mcp-playwright&lt;/a&gt;, which allows browser manipulation, direct console reading for error detection, and automatic correction.&lt;/p&gt;
&lt;p&gt;I happened to have a work-related task that required researching related matters, so I experimented with writing a Uniswap MCP using Protocolink and Moralis, allowing direct trading within Claude Desktop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;uniswap-mcp.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1704&quot; height=&quot;1344&quot; src=&quot;/_astro/uniswap-mcp.CdheqHGK_18vyDW.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;You can watch the demonstration at &lt;a href=&quot;https://www.youtube.com/watch?v=7fRmwQYaBLg&quot;&gt;this YouTube link&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After completing this, it made me reflect on the development of messaging apps over the past decade. Initially, LINE MINI App and Telegram Mini Apps became popular, but later most functionality was redirected to external web pages, with only small, simple UI elements embedded within messaging conversations. I would take the same approach, as implementing on external sites is simpler—only the most essential user authentication needs to be handled within LINE.&lt;/p&gt;
&lt;p&gt;A few months ago, when I saw Vercel’s AI SDK 3.0, it was a moment when I realized that future software user interfaces might be very different. Their announcement included a tool that could generate a weather display interface directly after querying the weather.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;vercel-ai-sdk.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1653&quot; height=&quot;757&quot; src=&quot;/_astro/vercel-ai-sdk.B-R26kZc_1WPIDt.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I initially thought it was completely dynamic UI generation, but after carefully reading the documentation, I found that you still need to &lt;a href=&quot;https://sdk.vercel.ai/docs/ai-sdk-ui/generative-user-interfaces#create-ui-components&quot;&gt;predefine UI components&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even if they haven’t achieved that yet, it opened up a space for imagination: What if UI components could dynamically assemble appropriate UI interfaces based on the context of received data? What if future user interactions are completely different from today? Will it be voice conversations followed by completely dynamic generation of suitable user interfaces?&lt;/p&gt;
&lt;p&gt;What kind of impact will this have on our industry?&lt;/p&gt;
&lt;p&gt;I think projecting or imagining the future is an interesting endeavor. The future appears chaotic yet interesting, but I hope the interesting aspects outweigh the chaos.&lt;/p&gt;
&lt;h2 id=&quot;postscript&quot;&gt;Postscript&lt;/h2&gt;
&lt;p&gt;This uniswap-mcp was written solely for research purposes, and 99% of the code was written by Cursor. We all know that we shouldn’t pass private keys into programs through environment variables, but for those who are still curious, here’s the source code. Please only use it for testing and research purposes, and don’t put too much money into it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yurenju/uniswap-mcp&quot;&gt;https://github.com/yurenju/uniswap-mcp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Tech</category></item><item><title>Before the Perplexity Comet Browser Release</title><link>https://yurenju.blog/en/posts/2025-02-25_before-perplexity-comet/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2025-02-25_before-perplexity-comet/</guid><pubDate>Tue, 25 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;perplexity-comet-browser.jpg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1966&quot; height=&quot;745&quot; src=&quot;/_astro/perplexity-comet-browser.BynsB0Tb_Z1LJI8J.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Perplexity is about to launch a new browser called Comet. While we don’t know what it will actually look like, it’s interesting to imagine. Suppose this browser enables human-AI collaboration for web browsing. For instance, when you need to find information, it could search across various search engines, read through results, and organize the data for you. If you need to update Google Docs or Notion, it could directly open the web page and modify the document. If that’s the case, the impact could be quite significant.&lt;/p&gt;
&lt;p&gt;I once heard a reason for building humanoid robots: the entire world is designed with humans as the reference point—stairs, door handles, washing machines, TV remotes, and so on. If a new creation takes a different form, it won’t be able to interact with the infrastructure that has been accumulated over hundreds or thousands of years.&lt;/p&gt;
&lt;p&gt;I think this browser feels somewhat similar. Traditionally, if web services wanted to allow machine access, they had to develop new APIs. They even implemented human verification systems like reCAPTCHA to counter various automated crawlers.&lt;/p&gt;
&lt;p&gt;But if the next generation of browsers enables human-AI collaboration for web browsing, suddenly much of the existing infrastructure becomes accessible. Automation barriers disappear—when human intervention is needed, the AI requests your assistance, then continues working once you’ve helped. Imagining this future reveals a very different world. Many cross-service integrations that previously seemed complex suddenly become simple—though we’ll also need to solve many new problems 🤣&lt;/p&gt;
&lt;p&gt;The future remains chaotic yet fascinating. I hope the fascinating parts outweigh the chaos.&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>ChatGPT as a Reflection and Extension of Curiosity</title><link>https://yurenju.blog/en/posts/2024-04-29_chatgpt-curiosity-reflection/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2024-04-29_chatgpt-curiosity-reflection/</guid><pubDate>Mon, 29 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Cover image&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1000&quot; height=&quot;1000&quot; src=&quot;/_astro/cover_chatgpt-curiosity-reflection.UmRChsBz_Z1NS59j.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;The root of originality is curiosity. Just as a good &lt;strong&gt;question&lt;/strong&gt; is itself an essential component of the &lt;strong&gt;answer&lt;/strong&gt;, curiosity is also a form of original power. — Paul Graham&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Recently, I’ve been using ChatGPT extensively in my daily life—proofreading my articles, having it offer counterarguments when I take notes, and using it to further understand various questions that puzzle me. Of course, I also question its answers. The more I use it, the more I realize it’s a kind of projection. It’s like a knowledgeable dialogue machine that occasionally gets details wrong. But when you don’t speak to it, it won’t proactively solve your questions.&lt;/p&gt;
&lt;p&gt;Only when you ask does this dialogue machine methodically organize its response.&lt;/p&gt;
&lt;p&gt;In the interview “&lt;a href=&quot;https://www.youtube.com/watch?v=pVr3sEeus6E&amp;#x26;t=1400s&quot;&gt;Naoki Urasawa × Mai Yoneyama Special Drawing Conversation&lt;/a&gt;,” Naoki Urasawa shared his views on AI drawing tools. He mentioned that when creating an incredibly magnificent sunset scene in animation, hand-drawing would take an enormous amount of time, and AI drawing tools could help in such cases. However, before that, you must already have your own imagination of that magnificent scene in your mind to subsequently use AI drawing as an aid.&lt;/p&gt;
&lt;p&gt;“If there’s no image in your head, it won’t work either,” Naoki Urasawa said.&lt;/p&gt;
&lt;p&gt;Coming back to my own use of ChatGPT, I also assign it roles. For example, the role I use for proofreading notes is “You are a strict editor who will offer counterarguments or criticisms to my notes and suggest how to revise the content.” But when you set a role for it, you’re imposing your needed functions and perspectives onto it. So you’re conversing with an extended version of yourself—one that simply has a larger knowledge base. But you set its perspective, role, and tasks, and these settings are what truly provide originality.&lt;/p&gt;
&lt;p&gt;As someone full of curiosity, I continuously ask it various questions. When facing difficulties, I dialogue with this extended role I’ve established, allowing myself to better understand my own views through iterative cycles. On the surface, I use ChatGPT to seek answers, but the underlying source of power is curiosity and questioning.&lt;/p&gt;
&lt;p&gt;To me, ChatGPT is a projection and extension of curiosity. Ultimately, what matters is the person asking the questions.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;Quoted from Chou Chin-Hua’s translation of “&lt;a href=&quot;https://www.facebook.com/chouchinhua/posts/pfbid03cpFHNMvCMmDmkv682Ec283EJrpmwqErZZFTKBprmaj4PU5QuZPTdWoo3karioszl&quot;&gt;How to Do Great Work&lt;/a&gt;” Facebook post, with minor textual adjustments by me &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>Tech</category></item><item><title>tw-did Additional Information</title><link>https://yurenju.blog/en/posts/2024-02-08_tw-did-additional-info/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2024-02-08_tw-did-additional-info/</guid><pubDate>Thu, 08 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the previous article, I mentioned that the collaboration structure of this project is somewhat complex. Every time someone asks me about it, I have to spend a lot of time explaining, so I’m writing it down here so that in the future I can just direct people to read this short article.&lt;/p&gt;
&lt;p&gt;The origin of this project was actually a contract bid issued by the Ministry of Digital Affairs (MODA), which was won by the Frontier Foundation. Most of the members from the Frontier Foundation participating in this contract came from the DA0 community. This contract actually included many projects, one of which was the verification project connecting W3C DIDs (Decentralized Identifiers) and the Mobile Citizen Digital Certificate - the open-source project I’m involved in. However, &lt;strong&gt;I did not participate in the contract bid&lt;/strong&gt; - this is where it gets complicated 😎&lt;/p&gt;
&lt;p&gt;As mentioned earlier, I was invited by the Ethereum Foundation and accepted their Grant Program. This was because some enthusiastic individuals within the foundation believed that such integration opportunities between &lt;strong&gt;decentralized identity&lt;/strong&gt; and government agencies are very rare, and they hoped to achieve this through open-source methods that serve the public interest. After discussions, the foundation decided to provide &lt;strong&gt;technical support&lt;/strong&gt; for this project. The method of this technical support was to find a suitable person through the Grant Program to be responsible for planning and implementing this project, and that’s how I became involved.&lt;/p&gt;
&lt;p&gt;So under this technical support framework, I accepted the Ethereum Foundation’s Grant Program to provide technical support for this project, including design, planning, and development, ultimately delivering the source code to the Frontier Foundation to complete the contract. I did not develop this project alone - several other developers also participated in frontend development, deployment, and other work. For details, please see the &lt;a href=&quot;https://github.com/moda-gov-tw/tw-did?tab=readme-ov-file#contributors&quot;&gt;contributors section of the README&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From my perspective, I participated in an open-source project and received a grant from the Ethereum Foundation. I have no contractual relationship with the Frontier Foundation and did not participate in the contract bid. I was merely a participant in an Ethereum Foundation grant program, providing technical support and developing an open-source project.&lt;/p&gt;
&lt;p&gt;This grant program ended at the end of December. After it ended, in mid-January, Doni from the Ministry of Digital Affairs asked if I was interested in providing a two-week technical feasibility assessment for the upcoming &lt;strong&gt;Taiwan Digital Identity Wallet draft&lt;/strong&gt;. At that point, I participated as a consultant in the MODA draft technical assessment, and this consulting work also ended at the end of January.&lt;/p&gt;
&lt;p&gt;So if you heard that Noah from DA0 was responsible for this project, that’s correct. Noah was primarily responsible for most of the coordination work, publicity, and exchange activities in this project. If you also heard that the Ethereum Foundation sponsored this development work, that’s also correct, because I participated in the planning and development of this project as technical support.&lt;/p&gt;
&lt;p&gt;I hope this explanation helps everyone understand this complex collaboration relationship 🤣&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>Proof of Concept: Privacy-First Digital Identity for Taiwan Residents</title><link>https://yurenju.blog/en/posts/2024-02-04_taiwan-digital-id-privacy-first/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2024-02-04_taiwan-digital-id-privacy-first/</guid><pubDate>Sun, 04 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the W3C DIDs series of articles, starting with “&lt;a href=&quot;https://yurenju.blog/posts/2023-08-21_fb-ban-and-did-solution/&quot;&gt;Digital Identity Issues from Facebook Account Bans and the DID Solution&lt;/a&gt;,” I pointed out that current digital identities are controlled by large corporations like Google or Facebook, who can delete your digital identity without your permission or consent. The second article, “&lt;a href=&quot;https://yurenju.blog/posts/2024-01-01_w3c-dids-redefining-identity-authority/&quot;&gt;W3C DIDs: A Digital Identity Standard That Dismantles Power Structures&lt;/a&gt;,” explored in depth how the DIDs and VC standards can solve issues of digital identity autonomy and privacy. The third article, “&lt;a href=&quot;https://yurenju.blog/posts/2024-02-02_semaphore/&quot;&gt;Semaphore: A Privacy-Enhanced Identity Solution&lt;/a&gt;,” provided a deeper understanding of how cutting-edge technologies like Semaphore offer &lt;strong&gt;anonymous yet verifiable&lt;/strong&gt; development kits.&lt;/p&gt;
&lt;p&gt;This article will integrate the above information to explain the project I developed in the second half of last year.&lt;/p&gt;
&lt;p&gt;Thanks to Phini from the Ethereum Foundation for the invitation. In the second half of 2023, I received funding from the Foundation’s Grant Program to participate in a multi-party collaborative project and develop an experimental project called &lt;a href=&quot;https://github.com/moda-gov-tw/tw-did&quot;&gt;tw-did&lt;/a&gt;, which integrates Taiwan’s Mobile Natural Person Certificate, W3C DIDs/VC, and the Semaphore zero-knowledge proof framework to improve the autonomy and privacy issues present in centralized digital identity solutions.&lt;/p&gt;
&lt;p&gt;This project has now been transferred to the Ministry of Digital Affairs (MODA). The collaboration structure of this project is somewhat complex, and I will supplement the details in a subsequent &lt;a href=&quot;https://yurenju.blog/posts/2024-02-08_tw-did-additional-info/&quot;&gt;short article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, let me introduce the &lt;strong&gt;Mobile Natural Person Certificate&lt;/strong&gt;, which hasn’t been mentioned before.&lt;/p&gt;
&lt;h2 id=&quot;mobile-natural-person-certificate&quot;&gt;Mobile Natural Person Certificate&lt;/h2&gt;
&lt;p&gt;When filing taxes in Taiwan, the most convenient method is to use online tax filing directly. One of the identity verification methods is the &lt;strong&gt;Natural Person Certificate&lt;/strong&gt;. The Natural Person Certificate is a chip card with a private key stored in a secure chip. It can be used for signing and verification through a card reader, serving as a digital certificate for Taiwan residents.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Inserting the Natural Person Certificate Card&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1998&quot; height=&quot;1520&quot; src=&quot;/_astro/moica.KJjQ9Pom_ZA9Nf9.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Residents who don’t yet have a card need to apply in person at a household registration office. After the office issues the physical card, this chip card can be used at other government agencies, such as for online tax filing services.&lt;/p&gt;
&lt;p&gt;While the Natural Person Certificate is secure, the disadvantage of the physical card is that it requires a chip card reader to use. Even though this chip card also supports NFC contactless reading, in most cases, an insertion-type card reader is needed. In addition to requiring an additional card reader for computer use, it’s also difficult to use on smartphones.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Mobile Natural Person Certificate&lt;/strong&gt; was developed to solve this inconvenience problem. The &lt;strong&gt;Mobile Natural Person Certificate&lt;/strong&gt; is an extended solution to the &lt;strong&gt;Natural Person Certificate&lt;/strong&gt;. After downloading the Mobile Natural Person Certificate app, Android devices can use NFC to read information from the Natural Person Certificate card and bind this physical card to the smartphone. In the future, users can directly use the smartphone app as a Natural Person Certificate card.&lt;/p&gt;
&lt;p&gt;During verification, it is protected by biometric authentication such as fingerprint or face recognition. After unlocking, the private key in the secure hardware is used for signing and identity verification.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Binding and Verification of Mobile Natural Person Certificate&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1998&quot; height=&quot;1126&quot; src=&quot;/_astro/twfido.CC61zhp2_1raSrd.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;The Mobile Natural Person Certificate solves the inconvenience of the physical chip card, allowing identity verification as a Taiwan resident through a smartphone. If the goal is convenience, it indeed solves a major problem. Additionally, it uses biometric verification devices, requires no password memorization, and stores the private key in the phone’s secure area, providing adequate security. Combined with fingerprint or facial recognition data that never leaves the phone, it’s an overall well-rounded solution.&lt;/p&gt;
&lt;p&gt;Of course, the Mobile Natural Person Certificate is still a centralized identity verification solution. We can examine this solution through the two main issues of current identity verification solutions mentioned in previous articles: &lt;strong&gt;autonomy&lt;/strong&gt; and &lt;strong&gt;privacy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Before that, it should be explained that when a user uses the Mobile Natural Person Certificate at an organization to verify their Taiwan resident identity, the Ministry of the Interior’s API will be used for the verification process.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Mobile Natural Person Certificate Relies on the Ministry of the Interior&amp;amp;#x27;s API&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1906&quot; height=&quot;1144&quot; src=&quot;/_astro/twfido-issues.CRiaMKmH_ZqCEsG.webp&quot; &gt;&lt;/p&gt;
&lt;h3 id=&quot;autonomy&quot;&gt;Autonomy&lt;/h3&gt;
&lt;p&gt;Although the Mobile Natural Person Certificate uses asymmetric cryptography for identity verification, the service issuer also participates in the verification process. This means that if the government wants to block a specific Taiwan resident, it can refuse to provide verification services through a blacklist when the verification process calls the API.&lt;/p&gt;
&lt;p&gt;To give an extreme example, suppose a foreign credit card company supports Taiwan residents applying for credit cards and integrates the Mobile Natural Person Certificate as a verification method. If Taiwan becomes an authoritarian state in the future and revokes all previously issued Taiwan resident certificates, even if this foreign credit card company is willing to accept applications from former Taiwan residents, the government can still easily use a blacklist to prevent anyone the government dislikes from passing verification.&lt;/p&gt;
&lt;h3 id=&quot;privacy&quot;&gt;Privacy&lt;/h3&gt;
&lt;p&gt;This has the same root as the autonomy issue. Because the issuer participates in the verification process, it means the government knows every time a user performs verification. This wasn’t a big problem before, because the Mobile Natural Person Certificate was only open to government agencies for verification procedures, and the public could accept the government tracking login behavior to other government agencies.&lt;/p&gt;
&lt;p&gt;However, after the second half of 2023, according to an &lt;a href=&quot;https://fido.moi.gov.tw/pt/main/news_detail/16&quot;&gt;announcement&lt;/a&gt;, the scope of application for the Mobile Natural Person Certificate has been expanded to &lt;strong&gt;non-governmental organizations&lt;/strong&gt;. At this point, privacy issues need more careful consideration. Imagine if a service like online banking requires using the Mobile Natural Person Certificate service to verify identity when logging in - the government can record every user’s digital footprint during login behavior, thus extending digital footprint collection to private enterprises.&lt;/p&gt;
&lt;p&gt;The above argument may seem to portray the government negatively, but that’s not actually the case. In &lt;a href=&quot;https://blocktrend.substack.com/p/ep235&quot;&gt;one episode of the Blocktrend podcast featuring an interview between Hsu Ming-En and DouNi&lt;/a&gt;, it was mentioned that if new technologies are not properly guided, technology may not necessarily move toward universally accepted values, because governments possess great power. If technology’s direction is not appropriately guided, it can easily go astray.&lt;/p&gt;
&lt;p&gt;If we have the opportunity to establish mechanisms and frameworks, we should design technology frameworks to move in a good direction as early as possible. Since we can design with &lt;strong&gt;autonomy and privacy first&lt;/strong&gt;, we should move in that direction.&lt;/p&gt;
&lt;h2 id=&quot;tw-did-experimental-project&quot;&gt;TW-DID Experimental Project&lt;/h2&gt;
&lt;p&gt;After explaining the Mobile Natural Person Certificate, I can finally introduce this project. &lt;a href=&quot;https://github.com/moda-gov-tw/tw-did&quot;&gt;tw-did&lt;/a&gt; is an experimental project that integrates the Mobile Natural Person Certificate, W3C DIDs/VC standards, and the Semaphore zero-knowledge proof framework, using the project’s output to glimpse the future and examine current shortcomings.&lt;/p&gt;
&lt;p&gt;Regarding the autonomy and privacy issues that still exist in the aforementioned Mobile Natural Person Certificate, tw-did can solve these two problems by integrating the Mobile Natural Person Certificate to interface with and convert Taiwan resident qualification certificates into W3C VC format certificates. Furthermore, through Semaphore, privacy is pushed even further, making it completely unnecessary to disclose digital identity during the verification process.&lt;/p&gt;
&lt;p&gt;Next, we will explain in two parts: &lt;strong&gt;W3C DIDs/VC Integration&lt;/strong&gt; and &lt;strong&gt;Semaphore Integration&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;w3c-didsvc-integration&quot;&gt;W3C DIDs/VC Integration&lt;/h3&gt;
&lt;p&gt;tw-did provides a web service. This service first uses the Mobile Natural Person Certificate to log in and verify the user’s Taiwan resident identity, then verifies the user’s DID identity. After both pieces of information are successfully verified, a &lt;strong&gt;Verifiable Credential&lt;/strong&gt; (VC) format certificate is issued to the user, allowing the user to use this certificate on other websites where they need to prove they are a Taiwan resident.&lt;/p&gt;
&lt;p&gt;As introduced in “&lt;a href=&quot;https://yurenju.blog/posts/2024-01-01_w3c-dids-redefining-identity-authority/&quot;&gt;W3C DIDs: A Digital Identity Standard That Dismantles Power Structures&lt;/a&gt;,” both the &lt;strong&gt;issuer&lt;/strong&gt; and the &lt;strong&gt;holder&lt;/strong&gt; can adopt different DID Methods. However, to keep the experimental environment simple, the tw-did project uniformly adopts the Ethereum blockchain’s DID Method &lt;code&gt;did:ethr&lt;/code&gt; and Ethereum accounts as DID identifiers. When verifying DID identity, the common Ethereum verification method Sign-In with Ethereum (SIWE) is used to verify through MetaMask message signing that the user actually owns that account, thus proving they own the private key of that DID.&lt;/p&gt;
&lt;p&gt;After confirming through the Mobile Natural Person service that the holder is a Taiwan resident and owns that DID identifier, tw-did as the issuer can issue a VC format certificate to the user. When issuing, tw-did will use the issuer DID to sign the certificate and provide it to the holder for download and storage. The overall issuance flow is as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Issuance Flow of Mobile Natural Person Certificate Integrated with W3C DIDs/VC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1906&quot; height=&quot;1144&quot; src=&quot;/_astro/twfido-w3c-dids-vc-issuance.Dfu-eV_G_Z1c8seE.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Step 2 of the issuance flow still calls the Ministry of the Interior API and provides the user’s national ID number, but this is the only API call that discloses the holder’s identity. In the verification flow, which holder is performing verification is not disclosed.&lt;/p&gt;
&lt;p&gt;Assuming a bank now supports the W3C DIDs/VC standard verification flow, users can present this certificate to prove they are indeed Taiwan citizens. The flow diagram is as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Verification Flow Combining Mobile Natural Person Certificate with W3C DIDs/VC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2658&quot; height=&quot;1590&quot; src=&quot;/_astro/cover_twfido-w3c-dids-vc-verification.Bgg5zXuP_ySKtn.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;When a verification organization like a bank requests a user to provide a specific VC format certificate, it will also issue a cryptographic challenge. When the user receives this request, they will use the private key corresponding to their DID to respond to the cryptographic challenge, and package the original VC certificate, challenge, and challenge response (i.e., signature) together into a &lt;strong&gt;Verifiable Presentation&lt;/strong&gt; (VP) document to reply to the bank.&lt;/p&gt;
&lt;p&gt;The bank will then check whether the various contents of the VP format certificate are correct, and will additionally request the revocation list from the issuer. Because it does not query via API whether a &lt;strong&gt;specific certificate&lt;/strong&gt; has been revoked, but instead obtains the entire revocation list at once, allowing the verifier to find the revocation information for that certificate in the list themselves. This way, the issuer can remain unaware of which holder is currently performing verification, but can still determine whether it has been revoked.&lt;/p&gt;
&lt;p&gt;Finally, the Ministry of the Interior’s API will not be called. This also means the Ministry of the Interior does not participate in the verification flow.&lt;/p&gt;
&lt;p&gt;When verification succeeds and the bank confirms the user is a Taiwan resident, they can begin using the bank’s services. Similarly, let’s verify the digital identity autonomy and privacy under this architecture.&lt;/p&gt;
&lt;h4 id=&quot;autonomy-1&quot;&gt;Autonomy&lt;/h4&gt;
&lt;p&gt;When the bank verifies the user’s identity through a VP format certificate, the original VC certificate in the VP document already contains the issuer’s signature. The bank can directly use public information to verify the issuer’s signature without the issuer’s participation, so it also cannot block the verification flow.&lt;/p&gt;
&lt;p&gt;Although the issuer can mark a certificate as revoked, even so, the issuer’s signature on this certificate is still valid, because the signature result is &lt;strong&gt;non-repudiable&lt;/strong&gt;. This means that even if the certificate is revoked, the verifier can still decide whether to accept this certificate in such a situation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Various States of VC Are Verified Separately&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1352&quot; height=&quot;802&quot; src=&quot;/_astro/vc-autonomy.Z17fP81E_Z1eA3np.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;As shown in the above diagram, the various states of VC are verified separately. Verifying the expiration date does not affect verifying the issuer’s signature, and revoking the certificate does not affect verifying the issuer’s signature.&lt;/p&gt;
&lt;p&gt;To use the previous extreme example, suppose Taiwan becomes an authoritarian state in the future and revokes all former resident identities. When a verifier receives a user’s revoked certificate, they can still consider whether to accept such a certificate as proof, rather than placing all power in the issuer’s hands.&lt;/p&gt;
&lt;p&gt;Compared to cases where the issuer participates in the entire verification flow, the W3C DIDs/VC specification flow still possesses higher digital identity autonomy.&lt;/p&gt;
&lt;h4 id=&quot;privacy-1&quot;&gt;Privacy&lt;/h4&gt;
&lt;p&gt;This is also related to whether the issuer participates in the verification flow. When users present VC format certificates at the bank, the issuer cannot know about or track it. This ensures privacy protection during the verification flow.&lt;/p&gt;
&lt;p&gt;Under the conventional W3C DIDs/VC architecture, autonomy and privacy are already protected. Next, let’s see what benefits Semaphore integration can bring us.&lt;/p&gt;
&lt;h3 id=&quot;semaphore-integration&quot;&gt;Semaphore Integration&lt;/h3&gt;
&lt;p&gt;Compared to the general W3C DIDs standard verification procedure, Semaphore integration can achieve the purpose of &lt;strong&gt;verifying qualifications&lt;/strong&gt; even without &lt;strong&gt;disclosing DID identification&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the case of the tw-did experimental project, a conventional VC certificate will record the holder’s DID identification string (including the Ethereum account address), from which public key information can be parsed to verify whether this VC certificate is correct.&lt;/p&gt;
&lt;p&gt;But this also means the user’s Ethereum account address will be disclosed.&lt;/p&gt;
&lt;p&gt;With Semaphore integration, there is no need to provide DID identification at all to prove one has Taiwan resident qualifications. When applied to the Mobile Natural Person Certificate example, it means users do not need to disclose their Ethereum address to verify their Taiwan resident identity.&lt;/p&gt;
&lt;p&gt;However, as mentioned in the previous article, Semaphore is a development kit, not a standard like W3C DIDs. Therefore, the work we carried out in the tw-did experimental project was to attempt to integrate Semaphore into the W3C DIDs/VC standard. A better approach would be to establish a new DID Method like &lt;code&gt;did:semaphore&lt;/code&gt; and specify various interaction methods. However, considering time and implementation difficulty, we decided to first use &lt;code&gt;did:web&lt;/code&gt; to wrap the semaphore verification method as an experimental evaluation solution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Mobile Natural Person Certificate Integrated with Semaphore Framework&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2880&quot; height=&quot;1318&quot; src=&quot;/_astro/twfido-semaphore-issuance.B5W_mA9k_2ff9fV.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;In the Semaphore integration issuance flow, after the user confirms their Taiwan resident identity through the Mobile Natural Person Certificate service, the user will generate a Semaphore Identity on the client side. This identity consists of public and secret parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Public&lt;/strong&gt;: Commitment, functions similar to the public key part of asymmetric cryptography&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secret&lt;/strong&gt;: Trapdoor and nullifier, functions similar to the private key part of asymmetric cryptography&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The public commitment will be provided to tw-did, where it will be added to a Semaphore Group as proof of Taiwan resident qualification. The list of all commitments registered in tw-did can be obtained by anyone and is public data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Semaphore Verification Flow&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2652&quot; height=&quot;1740&quot; src=&quot;/_astro/twfido-semaphore-verification.DUfZOubw_Z23G8Vk.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;In the Semaphore verification process, a verifier like a bank will issue a cryptographic challenge, and only Semaphore Identities with Taiwan resident qualifications can generate the correct challenge response.&lt;/p&gt;
&lt;p&gt;This is divided into two steps: &lt;strong&gt;generating proof&lt;/strong&gt; and &lt;strong&gt;verification&lt;/strong&gt;. Generating proof is executed on the holder’s client side, while verification is performed by the verifier’s service.&lt;/p&gt;
&lt;p&gt;When the holder &lt;strong&gt;generates proof&lt;/strong&gt;, they need the cryptographic challenge, their own Semaphore Identity, and a list of all qualified commitments, of which the commitment list needs to be requested from tw-did. With these three input parameters, the corresponding proof can be generated.&lt;/p&gt;
&lt;p&gt;When the verifier &lt;strong&gt;verifies&lt;/strong&gt;, they need two input parameters. The first is the proof submitted by the holder, and the second is also the commitments list. With these two parameters, the proof can be verified.&lt;/p&gt;
&lt;p&gt;We can compare the proof verification flow of general asymmetric cryptography with Semaphore zero-knowledge proof.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Comparison of Semaphore with Conventional Asymmetric Cryptography&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1804&quot; height=&quot;1658&quot; src=&quot;/_astro/pkc-semaphore-comparison.CjK2Y9qd_Z1uT7Gt.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;General asymmetric cryptography uses a private key to sign, and the verifier needs to obtain the corresponding public key for verification. Since the public key represents the DID key pair, DID identity information will still be exposed to some degree. In the Semaphore verification flow, there is no need to provide a specific commitment corresponding to a specific identity, but only a list of all qualified commitments. This way, verification can be performed without disclosing identity.&lt;/p&gt;
&lt;p&gt;Compared to conventional W3C DIDs/VC, this further strengthens privacy. During verification, one can only know that the other party meets the qualifications, but cannot know who specifically. Conventional VC certificates must always include public key information, so if you don’t want the verifier to know your Ethereum account, you can use this more advanced Semaphore zero-knowledge proof to achieve enhanced privacy protection.&lt;/p&gt;
&lt;p&gt;However, it should be noted that the Semaphore integration is highly experimental, so some shortcuts were taken in development, making the current prototype’s digital identity autonomy not as good as conventional VC. But this is a clearly understood problem with known improvement methods, which will be discussed in the later &lt;strong&gt;Review and Discussion&lt;/strong&gt; section.&lt;/p&gt;
&lt;h2 id=&quot;demo-video&quot;&gt;Demo Video&lt;/h2&gt;
&lt;p&gt;This time I tried attaching a demonstration video with each milestone release. Looking back now, it’s quite interesting - I didn’t expect the project to change so much from August to October 😎&lt;/p&gt;
&lt;p&gt;You can see the introduction and videos for each milestone here: &lt;a href=&quot;https://github.com/moda-gov-tw/tw-did/releases&quot;&gt;https://github.com/moda-gov-tw/tw-did/releases&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here I’ll embed the Milestone 6 video:&lt;/p&gt;
&lt;p&gt;{{&amp;#x3C; rawhtml &gt;}}
&lt;video width=&quot;100%&quot; controls&gt;
&lt;source src=&quot;tw-did-select-credentials.mp4&quot; type=&quot;video/mp4&quot;&gt;
Your browser does not support the video tag.
&lt;/video&gt;
{{&amp;#x3C; /rawhtml &gt;}}&lt;/p&gt;
&lt;p&gt;There are two tabs here: the Web tab is the issuer, and the SampleVerifier tab is the verifier.&lt;/p&gt;
&lt;p&gt;In the Web tab, the user’s identity is first verified through the Mobile Natural Person Certificate service. In this service integration, a notification is sent through the &lt;strong&gt;Mobile Natural Person Certificate app&lt;/strong&gt; that the user has already installed, or the user can also choose to scan a QR code to perform the login procedure.&lt;/p&gt;
&lt;p&gt;After logging in, Sign-In With Ethereum is used to verify through signature whether the user actually owns an Ethereum account. The final step is to generate a Semaphore identity and register its commitment in the tw-did database.&lt;/p&gt;
&lt;p&gt;This completes the preliminary work for the issuance procedure.&lt;/p&gt;
&lt;p&gt;Finally, users can download two different types of VC certificates. The first is a VC certificate issued to the holder’s Ethereum account address, and the other is a VC certificate issued to the holder’s Semaphore Identity. The file names are &lt;code&gt;vc-ethereum.json&lt;/code&gt; and &lt;code&gt;vc-semaphore.json&lt;/code&gt;, respectively.&lt;/p&gt;
&lt;p&gt;Next is the SampleVerifier sample page for the verification procedure. This page is for development and debugging purposes, so it’s relatively bare-bones. The verification website can verify the two types of certificates issued above, for Ethereum and Semaphore respectively.&lt;/p&gt;
&lt;p&gt;In the Ethereum certificate verification part, users are first asked to select a VC certificate issued to an Ethereum address as a DID. Users can directly use the file selection function to select &lt;code&gt;vc-ethereum.json&lt;/code&gt; for verification, or press “Select on DID” to select the required Ethereum certificate on the issuance website. After selection, parsing work begins. When &lt;strong&gt;verify&lt;/strong&gt; is pressed, it signs through MetaMask and generates a VP document to confirm the holder’s qualifications.&lt;/p&gt;
&lt;p&gt;In the Semaphore certificate verification part, pressing &lt;strong&gt;Semaphore Challenge and verify&lt;/strong&gt; will have the verification website generate a cryptographic challenge in real-time, and the holder will generate proof on the client side, package it into a VC format certificate, and return it to the verification website for the verification procedure.&lt;/p&gt;
&lt;h2 id=&quot;review-and-discussion&quot;&gt;Review and Discussion&lt;/h2&gt;
&lt;p&gt;Looking at the GitHub commit history, I submitted the first commit in early August, and the project was completed at the end of October. Before learning about this project, my understanding of DID was very superficial, so both research and development were completed under very urgent conditions.&lt;/p&gt;
&lt;p&gt;Therefore, there are inevitably shortcomings in both research and implementation. Much was learned and done simultaneously, and some knowledge was only understood after the project ended regarding how to do better. I’ll write it here for future developers’ reference.&lt;/p&gt;
&lt;p&gt;This project has several most important goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Does this prototype provide imagination of future scenarios, helping to understand what we can do in future production environments?&lt;/li&gt;
&lt;li&gt;When these mechanisms are integrated together, are the autonomy and privacy of digital identity protected?&lt;/li&gt;
&lt;li&gt;Were problems encountered during development that can serve as reference for production environments?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;does-the-prototype-provide-imagination-of-future-scenarios&quot;&gt;Does the Prototype Provide Imagination of Future Scenarios&lt;/h3&gt;
&lt;p&gt;What was integrated in this experiment was the Mobile Natural Person Certificate, and the issued certificates can be used by another verification service to confirm whether this user is a Taiwan resident.&lt;/p&gt;
&lt;p&gt;We can imagine that in the future, this Taiwan resident certificate could be used by many services as audit data for identity verification, such as opening bank accounts, or e-commerce platforms auditing whether sellers are Taiwan residents.&lt;/p&gt;
&lt;p&gt;However, since it’s a prototype, at this stage, no verification units would actually trust this certificate. In the future, production environment certificates would still need to be issued by more formal organizations, such as the Ministry of the Interior or the Ministry of Digital Affairs, to increase verification organizations’ level of trust in this certificate. There may even need to be legal basis to use it in more formal settings.&lt;/p&gt;
&lt;p&gt;Regarding certificate storage, when imagining a future where multiple different certificates need to be stored, there will need to be a VC Wallet app to accomplish this purpose.&lt;/p&gt;
&lt;h3 id=&quot;digital-identity-autonomy-and-privacy&quot;&gt;Digital Identity Autonomy and Privacy&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, centralized digital identity lacks autonomy and privacy. Even the Mobile Natural Person Certificate service has the same problems. When a verification organization (especially non-governmental organizations) adopts the Mobile Natural Person Certificate as a verification method, there are different concerns regarding both autonomy and privacy. For example, as in the previous example, when opening a bank account, there are autonomy concerns that the government can directly block the verification procedure to prevent specific users from opening accounts, while simultaneously having privacy concerns that the government will know which bank users go to open accounts.&lt;/p&gt;
&lt;p&gt;After interfacing with the Mobile Natural Person Certificate and issuing VC certificates, the characteristic that the issuer doesn’t need to participate during verification ensures the autonomy and privacy of digital identity.&lt;/p&gt;
&lt;p&gt;In terms of autonomy, because the issuer does not participate in the verification procedure (except for the revocation list), they cannot erase a person’s digital identity by blocking the verification procedure. Even if the revocation function is used to mark a certificate as revoked, the issuer cannot deny having once signed and endorsed this digital certificate.&lt;/p&gt;
&lt;p&gt;In terms of privacy, similarly because the issuer does not participate in the verification procedure, the issuer cannot know which user is performing the verification procedure.&lt;/p&gt;
&lt;p&gt;Of course, during research and development, we encountered quite a few problems. Below I’ll share some related experiences.&lt;/p&gt;
&lt;h3 id=&quot;development-kits&quot;&gt;Development Kits&lt;/h3&gt;
&lt;p&gt;First, in this project, I used &lt;a href=&quot;https://veramo.io/&quot;&gt;Veramo&lt;/a&gt;, a TypeScript development kit. From the experience of developing this project, Veramo is quite flexible and not difficult to use. In this development, I implemented a new signature verification method &lt;code&gt;Semaphore2023&lt;/code&gt;. Although the process was somewhat convoluted, it was ultimately completed.&lt;/p&gt;
&lt;p&gt;However, since these are still relatively new development kits, W3C DIDs/VC-related developers don’t have as much attention as popular development frameworks like React or Vue, so the documentation isn’t as comprehensive. Therefore, when developing non-built-in features, it’s still necessary to read the source code to proceed.&lt;/p&gt;
&lt;p&gt;Because the project timeline was relatively tight, I didn’t do very in-depth research when initially selecting kits. Later, I saw several different development kits, such as SpruceID’s Rust-implemented &lt;a href=&quot;https://www.sprucekit.dev/&quot;&gt;SpruceKit&lt;/a&gt; and another TypeScript library implemented by Ceramic, &lt;a href=&quot;https://github.com/ceramicnetwork/js-did&quot;&gt;ceramicnetwork/js-did&lt;/a&gt;. These all look like choices worth trying, especially js-did, which appears to have &lt;a href=&quot;https://github.com/ceramicnetwork/js-did/tree/main/packages/key-webauthn&quot;&gt;functionality for integrating WebAuthn into did:key&lt;/a&gt;, worthy of deeper research.&lt;/p&gt;
&lt;h3 id=&quot;lack-of-wallet&quot;&gt;Lack of Wallet&lt;/h3&gt;
&lt;p&gt;At the time of implementation, I didn’t find a suitable VC Wallet to store certificates issued by the issuer. Originally, I had planned to quickly implement a Wallet, but due to time constraints, it wasn’t completed. You can find the &lt;a href=&quot;https://github.com/tw-did/tw-did/tree/main/apps/wallet&quot;&gt;wallet app&lt;/a&gt; on GitHub, which just had the frontend interface completed but logic not yet implemented. In the end, we put the credential selection functionality for the verification procedure on the issuer’s website. This doesn’t actually conform to the principle that the issuer doesn’t participate in the verification procedure, but considering there was no suitable VC Wallet found at the time of implementation, this was an acceptable experimental approach.&lt;/p&gt;
&lt;p&gt;Although nothing suitable was found initially, after the project ended, I discovered that Microsoft Authenticator, which Microsoft usually uses for two-factor authentication, supports storing VCs. See &lt;a href=&quot;https://learn.microsoft.com/en-us/entra/verified-id/using-authenticator&quot;&gt;this article&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;If we had discovered earlier that Microsoft Authenticator has this functionality, we would have referred to their integration method to allow certificates to be stored in the MS Authenticator app.&lt;/p&gt;
&lt;h3 id=&quot;lack-of-exchange-protocol&quot;&gt;Lack of Exchange Protocol&lt;/h3&gt;
&lt;p&gt;When initially reading W3C documents, there were no specifications on how to exchange credentials. Therefore, neither &lt;strong&gt;issuer issuing certificates to holders&lt;/strong&gt; nor &lt;strong&gt;holders presenting VPs to verifiers&lt;/strong&gt; were defined. Since there was no definition, the most intuitive method was to generate a certificate file for users to download, and verifiers would similarly submit a VC through the native file selection function of the webpage, letting users sign it and then convert it to a VP.&lt;/p&gt;
&lt;p&gt;While researching Microsoft Authenticator, we also discovered that the exchange protocol used by the app is the &lt;code&gt;openid-vc&lt;/code&gt; and &lt;code&gt;openid-vp&lt;/code&gt; standards established by another organization, OpenID.&lt;/p&gt;
&lt;p&gt;Although the initial implementation still achieved the experimental purpose, if actually implementing a production product, one could consider adopting the standard established by OpenID, and then use Microsoft’s Microsoft Authenticator as a VC Wallet to store certificates.&lt;/p&gt;
&lt;h3 id=&quot;semaphore-improves-privacy-but-implementation-details-need-refinement&quot;&gt;Semaphore Improves Privacy, But Implementation Details Need Refinement&lt;/h3&gt;
&lt;p&gt;Semaphore integration indeed greatly improved privacy, but because it’s experimental, there are indeed many implementation details that need refinement.&lt;/p&gt;
&lt;p&gt;For example, we used the &lt;code&gt;did:web&lt;/code&gt; DID Method and wrapped a new verification type &lt;code&gt;Semaphore2023&lt;/code&gt; inside it. Here, we actually extended a new verification type through Veramo, while simultaneously establishing an anonymous DID identity &lt;a href=&quot;https://tw-did.github.io/hidden/did.json&quot;&gt;did:web:tw-did.github.io:hidden&lt;/a&gt; on GitHub Pages. A better approach here might be to add a new DID method &lt;code&gt;did:semaphore&lt;/code&gt; and natively support anonymous identity.&lt;/p&gt;
&lt;p&gt;At the same time, there’s also the problem that other kits won’t support &lt;code&gt;Semaphore2023&lt;/code&gt;, this special verification type. For example, the previously mentioned MS Authenticator cannot use this verification type we defined ourselves. If the entire specification can be thought through clearly, registered in the &lt;a href=&quot;https://www.w3.org/TR/did-spec-registries/#did-methods&quot;&gt;DID Specification Registries&lt;/a&gt;, and promoted, it would be more appropriate.&lt;/p&gt;
&lt;p&gt;Additionally, the implementation of the verification procedure violates the principle of autonomy by requesting public information commitments list from the issuer. Because it’s requesting public information, it doesn’t cause privacy problems. However, the issuer can still choose not to provide commitments to block everyone from verifying their identity.&lt;/p&gt;
&lt;p&gt;This problem can be solved using the on-chain version of Semaphore. When using the on-chain version, many things can be achieved by directly interacting with smart contracts, and there’s no need to request the commitments list from the issuer, thus solving the autonomy problem. Of course, if blockchain needs to be used in the issuance mechanism, other problems unique to blockchain will arise, such as transaction fee expenditure issues.&lt;/p&gt;
&lt;p&gt;In short, there are still many places in the implementation details of integrating Semaphore into W3C DIDs that need refinement, and may require more iterations and discussions to find a more mature approach.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall, I think this experimental project is excellent. It glimpses the future through a key scenario - &lt;strong&gt;verifying Taiwan resident identity&lt;/strong&gt; - giving people concerned about this issue (that is, you who have read this article to this point) a more concrete outline of digital identity with greater autonomy and privacy. At the same time, the implementation part went far enough to understand obstacles that may be encountered in future production environments.&lt;/p&gt;
&lt;p&gt;On the other hand, it also explored more deeply whether the necessary technology is currently available if one wants to achieve the level of &lt;strong&gt;anonymous but verifiable qualifications&lt;/strong&gt; through zero-knowledge proof. It can also stimulate everyone’s imagination to think about how important such highly privacy-preserving technology is to us, and whether there are other negative impacts.&lt;/p&gt;
&lt;p&gt;Of course, for me, it was also a great exploration. I actually didn’t understand DID that well before, and only with this project did I truly gain a deep understanding of these matters.&lt;/p&gt;
&lt;p&gt;My plan for this year is to independently develop small services or apps, which won’t be related to DID or blockchain. However, I still hope that previous development experience can play some role. So if you want to find someone to discuss or exchange ideas about the DID topic, you can still contact me. I’ll allocate some time to this topic. While I won’t have time to develop projects, exchanging existing experience and perspectives is no problem. &lt;a href=&quot;mailto:spry.flag8191@fastmail.com&quot;&gt;Welcome to email me&lt;/a&gt;!&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>Semaphore: A Privacy-Enhanced Identity Solution</title><link>https://yurenju.blog/en/posts/2024-02-02_semaphore/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2024-02-02_semaphore/</guid><pubDate>Fri, 02 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When attending a concert, you simply need to present a paper ticket to enter the venue. Occasionally, for events requiring real-name registration, you may need to show identification. With paper tickets, staff can verify your identity without your movements being tracked.&lt;/p&gt;
&lt;p&gt;However, in digital life, it’s a different story.&lt;/p&gt;
&lt;p&gt;In digital life, when you need to prove your identity for verification, your authentication action is almost invariably recorded. Taking the same example, if you present an electronic ticket to enter a concert venue, there’s a high probability that your entry information will be logged.&lt;/p&gt;
&lt;p&gt;Often, these records serve meaningful purposes that users can understand and accept. For instance, entry and exit records are indeed necessary to prevent a single ticket from being used multiple times. However, the &lt;strong&gt;easy-to-track&lt;/strong&gt; nature of digital footprints has gone too far, resulting in many troublesome phenomena. The most common is that after browsing websites, Facebook and Google become flooded with related advertisements. It’s as if someone is following you down the street with a notebook, recording your every move—the magazines you flipped through at the convenience store, the drinks you like. Then repeatedly posting advertisements they think you’ll buy on the routes you take.&lt;/p&gt;
&lt;p&gt;In the past, implementations of identity login and verification never considered making this difficult to track, because effectiveness, ease of evaluation, and trackability are the strengths of digital records. But when people began to recognize the importance of digital footprints to privacy, they looked back to discover that the digital technologies we commonly use today don’t have that &lt;strong&gt;difficult-to-track&lt;/strong&gt; characteristic.&lt;/p&gt;
&lt;p&gt;And &lt;a href=&quot;https://semaphore.pse.dev/&quot;&gt;Semaphore&lt;/a&gt; is a mechanism born from this need.&lt;/p&gt;
&lt;p&gt;Semaphore is an identity verification mechanism implemented through Zero Knowledge Proof (ZKP) in cryptography. Traditional digital identity verification requires explicit input of your identification information. For example, when logging into a Google account, you need to enter your account name and password, and the account name itself is your identification information.&lt;/p&gt;
&lt;p&gt;In Semaphore’s usage scenarios, you don’t need to input information like &lt;strong&gt;account name&lt;/strong&gt;. Instead, it only verifies your &lt;strong&gt;qualification&lt;/strong&gt;, not the user’s specific corresponding digital identity. Let’s use the same ticketing platform scenario, but with three different technical implementations to explain this concept.&lt;/p&gt;
&lt;h2 id=&quot;example-scenario&quot;&gt;Example Scenario&lt;/h2&gt;
&lt;h3 id=&quot;paper-tickets&quot;&gt;Paper Tickets&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;ticket-paper.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2230&quot; height=&quot;1054&quot; src=&quot;/_astro/ticket-paper.CiiKZIXc_Z1eEJx8.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;When using paper tickets, Alice obtains a paper ticket after purchasing it from the ticketing website. At the event venue, she presents the ticket to staff member Bob, who checks whether the ticket is valid. If correct, Bob allows Alice to attend the event.&lt;/p&gt;
&lt;p&gt;Paper tickets have some inherent drawbacks. For instance, they require additional anti-counterfeiting measures to prevent others from forging tickets. Additionally, such scenarios can typically use electronic checking methods, such as QR code scanning verification to prevent a single ticket from being used twice. However, when adopting electronic checking mechanisms, they generally also record the user’s footprints.&lt;/p&gt;
&lt;h3 id=&quot;digital-tickets&quot;&gt;Digital Tickets&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;ticket-digital.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2230&quot; height=&quot;1582&quot; src=&quot;/_astro/ticket-digital.C-aDfr1K_Z2vIW9K.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;When using digital tickets, Alice must first log in to the ticketing platform with an account and purchase a ticket. After successful purchase, Alice is added to the audience list. Upon arrival at the event venue, she presents a QR code on her phone screen for entry. Bob verifies the ticket correctness through the QR code and then allows Alice to enter, with the system marking Alice’s ticket as having entered.&lt;/p&gt;
&lt;p&gt;The advantage of digital tickets is more convenient verification. Although there are technical issues to overcome, during entry, the backend database can quickly confirm whether the audience member is an attendee, and it can detect if multiple people use the same ticket for entry.&lt;/p&gt;
&lt;p&gt;The disadvantage is the digital footprint problem. It’s fine when used reasonably, but the current situation is far too abusive, especially with advertising.&lt;/p&gt;
&lt;h3 id=&quot;semaphore-identity-authentication&quot;&gt;Semaphore Identity Authentication&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;cover_ticket-semaphore.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2546&quot; height=&quot;1946&quot; src=&quot;/_astro/cover_ticket-semaphore.CYu0bfVc_WP1h.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Semaphore is a development kit to help developers create an &lt;strong&gt;anonymous yet verifiable&lt;/strong&gt; login mechanism. First, you still need to log in to the ticketing platform and purchase a ticket, but here the ticketing platform has users register their Semaphore Identity. If a name is entered, the ticketing platform will still know the user’s name and corresponding ID number. For example, after Alice registers, her ID number &lt;code&gt;0x1234&lt;/code&gt; will still correspond to her name Alice.&lt;/p&gt;
&lt;p&gt;On the event day when Alice enters, she similarly presents a QR code for entry. At this time, staff member Bob also scans the ticket, but this QR code doesn’t contain the user’s explicit identity verification information (such as account name or email). Instead, it allows the verifier to present a cryptographic challenge, and the user replies with a challenge solution without revealing their identity. This solution can only be answered by one of the attendees, thus proving they are an attendee without revealing who they actually are.&lt;/p&gt;
&lt;p&gt;This means that during ticket verification, the attendance list only shows information like &lt;code&gt;user1&lt;/code&gt;, &lt;code&gt;user2&lt;/code&gt;, &lt;code&gt;user3&lt;/code&gt;, &lt;code&gt;user4&lt;/code&gt;, which represent four attendees respectively, but the platform cannot know the correspondence between &lt;code&gt;userN&lt;/code&gt; and the actual attendee’s ID number.&lt;/p&gt;
&lt;p&gt;When Alice successfully verifies, the platform only knows that among these four attendees eligible to enter, one person has entered and three people have not yet entered. As for who exactly entered, the verifier has no way of knowing, and this ticket will be marked as used, preventing others from entering with the same ticket.&lt;/p&gt;
&lt;p&gt;All these functions are implemented based on zero-knowledge proof technology in cryptography, using cryptography to guarantee that the user’s qualifications can be verified without revealing their exact identity.&lt;/p&gt;
&lt;p&gt;This offers even stronger privacy protection compared to the W3C DIDs/VC mechanism. During VC verification, the user’s public key is unavoidably revealed, whereas Semaphore doesn’t reveal any user identification information.&lt;/p&gt;
&lt;h1 id=&quot;reasons-and-scenarios-for-using-semaphore&quot;&gt;Reasons and Scenarios for Using Semaphore&lt;/h1&gt;
&lt;p&gt;As mentioned earlier, the digital identity verification technologies commonly used today unavoidably disclose user identity. When these records are linked together, the resulting digital footprints pose a major threat to personal privacy. Shadow-like, inescapable advertisements aren’t annoying enough—even when users switch between two completely different account platforms, such as social networking sites and blog sites with no common account, advertisements can still follow everywhere. These things are extremely annoying.&lt;/p&gt;
&lt;p&gt;Another more worrying concern is website intrusion incidents. When hackers break into a website and users have a lot of data and footprints on that website, these things become materials for fraud or the next intrusion, spread across the boundless internet. For instance, I myself am relatively careful and cautious when using the internet, but Google One’s dark web monitoring function still shows that my data has been leaked in large quantities, and most of these leaks come from websites being compromised and sold on the dark web.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;google-one-results.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2258&quot; height=&quot;1894&quot; src=&quot;/_astro/google-one-results.q-X4nnR0_Z1g1cj.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;When more websites use technologies like Semaphore, the data stored on websites is minimized. In situations where even the website itself cannot identify users’ digital footprints, even if data is stolen, it becomes useless.&lt;/p&gt;
&lt;p&gt;Of course, such anonymous yet verifiable technology cannot be applied to all scenarios. Besides ticketing, here are some examples where Semaphore can be used for authentication. However, Semaphore can only solve privacy issues, and typically the examples involve many complex situations that need handling, but we’ll focus only on privacy issues here.&lt;/p&gt;
&lt;h3 id=&quot;online-alcohol-purchase&quot;&gt;Online Alcohol Purchase&lt;/h3&gt;
&lt;p&gt;Generally, when buying alcohol online, you don’t want your personal privacy identity information to be known, but age information needs to be verified. If after verifying identity with a specific service, people with adult qualifications can all obtain a Semaphore-compliant qualification certificate, then in the future when buying alcohol online, they just need to present this certificate without being tracked through specific identity identification to their digital footprints.&lt;/p&gt;
&lt;p&gt;When verifying age here, since you can only know whether qualifications are met but not the exact identity, retailers also won’t store any privacy data. Of course, the service providing identity verification still has privacy data, but the attack surface is much smaller.&lt;/p&gt;
&lt;h3 id=&quot;whistleblower-platforms&quot;&gt;Whistleblower Platforms&lt;/h3&gt;
&lt;p&gt;Whether for sexual harassment or various whistleblower platforms, there’s usually a need to verify that the user has the qualification to report specific incidents while maintaining anonymity. Imagine if when a company registers on a platform, it needs to register employees through semaphore identity into the system. When reporting is needed, Semaphore identity verification can serve as an identity verification method that can verify while maintaining anonymity.&lt;/p&gt;
&lt;p&gt;For example, on sexual harassment prevention platforms during reporting, it can be confirmed that the reporter actually worked at that company while maintaining anonymity.&lt;/p&gt;
&lt;h3 id=&quot;medication-or-poverty-assistance&quot;&gt;Medication or Poverty Assistance&lt;/h3&gt;
&lt;p&gt;Some medication assistance and poverty assistance can also be solved using similar methods when there are long-term stigmatization issues in society. For instance, assistance qualification lists can be established through Semaphore, but when receiving assistance, there’s no need to actually present identity, yet it can confirm they have the qualification to receive assistance.&lt;/p&gt;
&lt;h3 id=&quot;opinion-surveys&quot;&gt;Opinion Surveys&lt;/h3&gt;
&lt;p&gt;Opinion surveys (or electronic voting) are also scenarios that frequently need to verify identity while maintaining anonymity when expressing opinions. However, opinion surveys still have many problems to solve, with privacy being just one major issue among many more that need resolution. On this topic, I recommend watching Tom Scott’s YouTube video “&lt;a href=&quot;https://www.youtube.com/watch?v=LkH2r-sNjQs&quot;&gt;Why Electronic Voting Is Still A Bad Idea&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;The above are some examples I thought of, but generally speaking, any scenario that is &lt;strong&gt;anonymous but requires qualification verification&lt;/strong&gt; can adopt Semaphore as a development kit.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Semaphore, as a development kit built using zero-knowledge proof, can actually have many different applications in privacy. Of course, with improved privacy, this also means restricting the power of platforms.&lt;/p&gt;
&lt;p&gt;In the feedback from the previous article “&lt;a href=&quot;https://yurenju.blog/posts/2024-01-01_w3c-dids-redefining-identity-authority/&quot;&gt;W3C DIDs: Redefining Identity Authority&lt;/a&gt;,” there was one response that left a deep impression. It mentioned that such utopian mechanisms are beautiful but won’t be used by anyone. I actually partially agree with this view, because such mechanisms indeed require participation and investment from giant enterprises to succeed easily, and why would giant enterprises want to restrict their already powerful authority?&lt;/p&gt;
&lt;p&gt;However, since digital footprints and personal privacy issues deeply affect everyone, they have gradually attracted attention from various sides. For instance, the EU’s GDPR (General Data Protection Regulation) has begun to more strictly restrict the use of privacy data, and even the recent &lt;a href=&quot;https://github.com/eu-digital-identity-wallet/eudi-doc-architecture-and-reference-framework?tab=readme-ov-file&quot;&gt;European Digital Identity Wallet (EUDIW)&lt;/a&gt; will also adopt the W3C Verifiable Credentials 1.1 standard, further strengthening privacy protection from the perspective of cross-national regulations and supervision.&lt;/p&gt;
&lt;p&gt;Meanwhile, Apple, which relies relatively less on profiting from privacy, has also introduced App Tracking Transparency in recent years, allowing users to decide for themselves whether to disclose their digital footprints to apps. These are all signs of gradually repairing digital footprint issues.&lt;/p&gt;
&lt;p&gt;I’m a relatively pessimistic person, and I also agree that these privacy-related developments won’t change the world very quickly. But seeing these developments still brings a bit of hope—we can’t just pessimistically tell the teacher that they don’t understand the bully just because the bully always picks on the victim. Changing people’s views or habits is very difficult, but I also hope to provide some assistance within my capabilities.&lt;/p&gt;
&lt;p&gt;Coming back to the topic, Semaphore, as a development kit, has the function of enabling developers to develop identity verification mechanisms that better conform to privacy principles. However, it’s not a standard like W3C DIDs but a more foundational development kit, so developers still need to build more complete privacy-first identity verification mechanisms.&lt;/p&gt;
&lt;p&gt;Now some projects are gradually introducing Semaphore’s identity verification mechanism.&lt;/p&gt;
&lt;p&gt;For example, &lt;a href=&quot;https://github.com/proofcarryingdata/zupass&quot;&gt;zuzalu passport (zupass)&lt;/a&gt;, as a conference/event identity verification platform, adopts Semaphore as the foundational infrastructure for zupass identity verification and released the Proof-Carrying Data (PCD) SDK as a credential solution. Zupass is like a lightweight DID solution but doesn’t deliberately comply with W3C DIDs/VC standards.&lt;/p&gt;
&lt;p&gt;Additionally, &lt;a href=&quot;https://developer.unirep.io/&quot;&gt;UniRep&lt;/a&gt;, as an anonymous reputation system that can receive and grant reputation, also adopts Semaphore as the underlying identity identification solution.&lt;/p&gt;
&lt;p&gt;Overall, Semaphore is still a very novel solution, and while from a developer’s perspective, Semaphore has already packaged the zero-knowledge proof framework for identity verification in a very easy-to-use manner, these cryptographic technologies are still a cutting-edge field. Developers still need to understand the concepts of the entire technology and also need to carefully evaluate various aspects of the development kit through experimental attempts.&lt;/p&gt;
&lt;p&gt;Therefore, Semaphore still has a way to go before large-scale application, but as more people pay attention to such privacy-focused technologies, I believe there will be opportunities to improve privacy issues on the internet.&lt;/p&gt;
&lt;h3 id=&quot;to-be-continued&quot;&gt;To Be Continued…&lt;/h3&gt;
&lt;p&gt;As for why I’m introducing Semaphore in the W3C DIDs series of articles? Mainly because in the second half of last year, I worked on a project that integrated Taiwan’s Ministry of the Interior’s Mobile Natural Person Certificate, W3C DIDs, and the Semaphore zero-knowledge proof framework, experimentally verifying the possibility of integrating these different technologies while evaluating various pros and cons.&lt;/p&gt;
&lt;p&gt;This actually stacks the privacy protection of W3C DIDs and VC with Semaphore, pushing privacy protection further forward to more cutting-edge and unknown edges. In such a state, we can more easily observe various aspects of these technologies.&lt;/p&gt;
&lt;p&gt;However, whether it’s W3C DIDs/VC, Semaphore, or even &lt;strong&gt;decentralized identity&lt;/strong&gt; itself, they are all very difficult to explain clearly at once. That’s why this series of articles was created to lay out all the knowledge. The next article will be the last in the series. I hope to have the opportunity to finish writing and publish it this month. Stay tuned!&lt;/p&gt;</content:encoded><category>Tech</category></item><item><title>W3C DIDs: A Digital Identity Standard Dismantling Power Structures</title><link>https://yurenju.blog/en/posts/2024-01-01_w3c-dids-redefining-identity-authority/</link><guid isPermaLink="true">https://yurenju.blog/en/posts/2024-01-01_w3c-dids-redefining-identity-authority/</guid><pubDate>Mon, 01 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Cover photo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1200&quot; height=&quot;960&quot; src=&quot;/_astro/cover_w3c-dids.D2T3-6Yb_Z28QGsx.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;In the previous related article &lt;em&gt;&lt;a href=&quot;https://yurenju.blog/posts/2023-08-21_fb-ban-and-did-solution/&quot;&gt;Examining Digital Identity Issues and DID Solutions Through Facebook’s Unjust Account Suspension&lt;/a&gt;&lt;/em&gt;, I revisited the current state of digital identity through my own tragedy of being suspended by Facebook without cause, and briefly mentioned &lt;a href=&quot;https://w3c.github.io/did-core/&quot;&gt;W3C DIDs&lt;/a&gt;, a standard attempting to disrupt this status quo. Now I want to explore more deeply how the W3C DIDs mechanism can transform the current landscape.&lt;/p&gt;
&lt;p&gt;Readers who haven’t read the &lt;a href=&quot;https://yurenju.blog/posts/2023-08-21_fb-ban-and-did-solution/&quot;&gt;previous article&lt;/a&gt; may want to revisit it first 😎&lt;/p&gt;
&lt;h2 id=&quot;current-state&quot;&gt;Current State&lt;/h2&gt;
&lt;p&gt;From my perspective, current digital identity services have several issues:&lt;/p&gt;
&lt;h3 id=&quot;autonomy&quot;&gt;Autonomy&lt;/h3&gt;
&lt;p&gt;Current digital identities are not owned by users but by large corporations, which &lt;strong&gt;allow&lt;/strong&gt; you to use those digital identities—just like how my Facebook account was permanently deleted without requiring my consent.&lt;/p&gt;
&lt;h3 id=&quot;privacy&quot;&gt;Privacy&lt;/h3&gt;
&lt;p&gt;Identity providers (i.e., companies like Google and Facebook) can track users’ login behavior, and users’ digital footprints serve as their monetization tools. Through users’ digital footprints, they can fuel their advertising and generate substantial profits. Combined with other services owned by these companies, such as Google’s search engine, Facebook’s social network, and the Facebook comment functionality embedded in websites, they can piece together a complete picture of users and serve them advertisements they’d like—or even &lt;a href=&quot;https://www.youtube.com/watch?v=PAr1F5keUGw&quot;&gt;scam ads they’re more likely to fall for&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But how do DIDs solve these problems? First, let’s gain a deeper understanding of DIDs.&lt;/p&gt;
&lt;h2 id=&quot;w3c-dids&quot;&gt;W3C DIDs&lt;/h2&gt;
&lt;p&gt;W3C Decentralized Identifiers (DIDs) is a standard for &lt;strong&gt;decentralized identity&lt;/strong&gt;, allowing users to perform identity verification using cryptography-based digital identities. In practice, when using W3C DIDs, it’s often necessary to combine them with another standard: &lt;strong&gt;W3C Verifiable Credentials (VCs)&lt;/strong&gt;. These two standards handle different functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DIDs standard: How to verify a DID identity&lt;/li&gt;
&lt;li&gt;VCs standard: The credential issued when one DID endorses a claim about another DID&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, when Alice purchases a game called &lt;em&gt;First Fantasy&lt;/em&gt;, developed by game developer “SE”, on a gaming purchase platform (let’s call it Stream), Stream will issue Alice a proof of game purchase.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;VC and DID game purchase example&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1464&quot; height=&quot;806&quot; src=&quot;/_astro/did-game-example.D-OsAG46_ZgU9vi.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;In this scenario, Stream as the platform will have a DID identity, and Alice will also have a personal DID identity. Before Alice purchases the game, Stream will first find verification information from Alice’s DID identity and verify this Alice DID identity. The DID standard specifies what this verification information should be.&lt;/p&gt;
&lt;p&gt;After Alice passes DID verification and purchases the game, Stream will issue Alice a game purchase proof in VC standard format, where Stream’s DID serves as the issuer, certifying that Alice purchased the game &lt;em&gt;First Fantasy&lt;/em&gt; on Stream. This is a credential generated to endorse a specific claim. Systems that receive this credential can verify whether the information recorded in the VC is correct based on the information contained within. This is the functionality provided by the VC standard.&lt;/p&gt;
&lt;p&gt;A DID identity looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;did-identifier&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1442&quot; height=&quot;450&quot; src=&quot;/_astro/did-identifier.iX90NUK5_1m4Vg2.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;A DID identity consists of three fields separated by colons. The first field is always the string &lt;code&gt;did&lt;/code&gt;, the second field is the DID Method. Since there are many different types and platforms for cryptography-based digital identities—including blockchain platforms, non-blockchain platforms, public key information placed on users’ own websites, and even locally generated public keys—the access methods for these different DID types are called DID Methods, and the second field indicates which DID Method this DID identity uses. The third field is an identifier string specific to the particular DID Method.&lt;/p&gt;
&lt;p&gt;For example, the following DID identity: &lt;code&gt;did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a&lt;/code&gt; means:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;did&lt;/code&gt;: This is a DID identity&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ethr&lt;/code&gt;: This DID identity uses the &lt;code&gt;ethr&lt;/code&gt; DID Method&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xb9c5...6e8a&lt;/code&gt;: The user uses this string to represent a specific identity in this DID Method (think of it as an ID number)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This DID identity string, when parsed through an appropriate library, can reveal how to interact with this DID—for example, how to verify identity or verify credentials. This interaction information is a JSON file called a DID Document.&lt;/p&gt;
&lt;p&gt;Here are a few different DID Methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;did:key&lt;/code&gt;: Users directly provide the public key in the DID identity string, without placing public key information elsewhere&lt;/li&gt;
&lt;li&gt;&lt;code&gt;did:web&lt;/code&gt;: Users place public key information on their own website&lt;/li&gt;
&lt;li&gt;&lt;code&gt;did:ethr&lt;/code&gt;: Users specify their account address on the Ethereum blockchain as the DID identity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Besides these three, there are many more DID Methods. For more types, please refer to &lt;a href=&quot;https://www.w3.org/TR/did-spec-registries/&quot;&gt;DID Specification Registries&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;didkey&quot;&gt;did:key&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;did:key&lt;/code&gt; means the DID identity string itself contains public key information, so no blockchain or other place to store the public key is needed. For example, in the DID identity &lt;code&gt;did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK&lt;/code&gt;, the third part &lt;code&gt;z6Mk...2doK&lt;/code&gt; is the public key of an algorithm, and this information is sufficient to verify this DID identity. To determine which encryption algorithm, you can judge from the beginning of the third field, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;z6Mk&lt;/code&gt;: Ed25519 algorithm&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zQ3s&lt;/code&gt;: Secp256k1 algorithm&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zDn&lt;/code&gt;: P-256 algorithm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the above example &lt;code&gt;z6Mk...2doK&lt;/code&gt; can be identified as requiring the Ed25519 algorithm to verify messages.&lt;/p&gt;
&lt;p&gt;The advantage of &lt;code&gt;did:key&lt;/code&gt; is that it’s very simple and managed by users themselves. If packaged as an app, it can even use biometric devices like TouchID to securely store the private key, making it a very convenient choice. The disadvantage is less flexibility—for example, if you want several different devices like phones and computers to manage one DID identity, there isn’t a secure management method.&lt;/p&gt;
&lt;p&gt;Another disadvantage is that the current format of &lt;code&gt;did:key&lt;/code&gt; doesn’t support the &lt;a href=&quot;https://webauthn.io/&quot;&gt;WebAuthn&lt;/a&gt; format, so you can’t use biometric devices directly on web pages to manage &lt;code&gt;did:key&lt;/code&gt;—it must be packaged as a mobile app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2024-02-05 Update&lt;/strong&gt;: I recently saw &lt;a href=&quot;https://github.com/ceramicnetwork/js-did/tree/main/packages/key-webauthn&quot;&gt;ceramicnetwork/js-did/key-webauthn&lt;/a&gt;, which looks like it might be possible to generate and verify &lt;code&gt;did:key&lt;/code&gt; using WebAuthn.&lt;/p&gt;
&lt;h3 id=&quot;didweb&quot;&gt;did:web&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;did:web&lt;/code&gt; is a method where users provide DID interaction information by uploading a JSON to a specific URL. For example, the DID identity &lt;code&gt;did:web:mattr.global&lt;/code&gt; actually obtains DID identity information from the URL &lt;a href=&quot;https://mattr.global/.well-known/did.json&quot;&gt;https://mattr.global/.well-known/did.json&lt;/a&gt;. The owner of this DID can adjust their identity verification requirements by changing this JSON file placed on the website—for example, they can have different cryptographic keys on multiple devices, allowing them to log in on phones, computers, and tablets, or they can regularly update and replace keys to maintain security.&lt;/p&gt;
&lt;p&gt;The advantage of &lt;code&gt;did:web&lt;/code&gt; is also its simplicity, and updating is very convenient. I think because people feel they &lt;strong&gt;own&lt;/strong&gt; that URL, they feel it’s quite secure. The disadvantage is that it’s not particularly convenient for ordinary people. A simple method might be to upload a file to Github pages—easy for engineers but somewhat difficult for average users.&lt;/p&gt;
&lt;p&gt;However, from a &lt;strong&gt;decentralization&lt;/strong&gt; perspective, &lt;code&gt;did:web&lt;/code&gt; has some drawbacks. For example, if it’s on Github Pages, when you have a conflict of interest with Github and the company decides to remove your website, your digital identity is taken away. Not to mention that domain names, even when registered, have time limits, and you might also have conflicts of interest with domain registrars that could cause the domain to become invalid.&lt;/p&gt;
&lt;p&gt;Of course, from most people’s perspective, this method already has sufficient autonomy. But if you’re concerned, you can use the slightly less flexible &lt;code&gt;did:key&lt;/code&gt;, or consider the next solution, &lt;code&gt;did:ethr&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;didethr&quot;&gt;did:ethr&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;did:ethr&lt;/code&gt; is a DID Method that places DID identity interaction information on Ethereum or compatible blockchains. For example, in the DID identity &lt;code&gt;did:ethr:0xf3beac30c498d9e26865f34fcaa57dbb935b0d74&lt;/code&gt;, the third part is the account address, and users can use the private key controlling this account to verify this DID identity. The default verification method is signing a message, which is something Ethereum blockchain users do frequently and is quite intuitive.&lt;/p&gt;
&lt;p&gt;Besides being ready to use out of the box, it can also be advanced configured through a &lt;a href=&quot;https://etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b&quot;&gt;smart contract&lt;/a&gt;, allowing for multi-device/private key management of the same DID identity and advanced features like key updates and rotation.&lt;/p&gt;
&lt;p&gt;The advantage of &lt;code&gt;did:ethr&lt;/code&gt; is that, like &lt;code&gt;did:web&lt;/code&gt;, it has more options to adjust DID identity while being sufficiently &lt;strong&gt;decentralized&lt;/strong&gt;, guaranteeing that as long as you possess the corresponding private key, you have complete control over the DID identity. There are no intermediaries like cloud server providers or domain registrars who might have conflicts of interest with users and take away your digital identity.&lt;/p&gt;
&lt;p&gt;But the disadvantages are also obvious. Since &lt;code&gt;did:ethr&lt;/code&gt; uses blockchain technology, users who haven’t been exposed to blockchain will find the barrier too high and difficult to use.&lt;/p&gt;
&lt;h2 id=&quot;verifiable-data-vc&quot;&gt;Verifiable Data (VC)&lt;/h2&gt;
&lt;p&gt;VCs, like DID Documents, are JSON files. As previously stated, a VC is a credential issued by one DID to another DID to endorse a specific claim. Using the same example of the game purchase platform Stream, Stream’s DID might be &lt;code&gt;did:web:streamgame.com&lt;/code&gt;, and if Alice chooses to use her Ethereum blockchain account to represent her identity, her DID would be something like &lt;code&gt;did:ethr:0xf3beac30c498d9e26865f34fcaa57dbb935b0d74&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here we can also observe that the &lt;strong&gt;issuer&lt;/strong&gt; and &lt;strong&gt;holder&lt;/strong&gt; in a VC can use different DID Methods, so an issuer who stores their public key on a website can also issue a VC credential to a user who uses an Ethereum account address as their DID identity.&lt;/p&gt;
&lt;p&gt;When Alice purchases a game, Stream’s system will issue a VC game purchase credential to Alice, as shown in this example:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light vitesse-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#121212;color:#24292e;--shiki-dark:#dbd7caee; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;@context&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;https://www.w3.org/2018/credentials/v1&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;issuer&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;did:web:streamgame.com&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;credentialSubject&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;did:ethr:0xf3beac30c498d9e26865f34fcaa57dbb935b0d74&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;purchaseId&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;123456789&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;gameTitle&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;First Fantasy&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;purchaseDate&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;2023-12-31T15:00:00Z&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;paymentAmount&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#4C9A91&quot;&gt; 59.99&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;currency&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;USD&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;platform&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;PC&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;VerifiableCredential&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;issuanceDate&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;2023-10-30T07:57:06.000Z&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;proof&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#DBD7CAEE&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;JwtProof2020&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;jwt&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D&quot;&gt;eyJhbGci...2rzP0K5wow&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#C98A7D77&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#666666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This example describes that the issuer is &lt;code&gt;did:web:streamgame.com&lt;/code&gt;, the person who purchased the game is Alice’s DID &lt;code&gt;did:ethr:0xf3beac30c498d9e26865f34fcaa57dbb935b0d74&lt;/code&gt;, and the &lt;code&gt;credentialSubject&lt;/code&gt; field contains game purchase information.&lt;/p&gt;
&lt;p&gt;What’s important here is that the &lt;code&gt;proof&lt;/code&gt; field contains the issuer’s signature information for this VC. Anyone who obtains this file can verify whether it was indeed signed and issued by Steam. After Alice obtains this credential, she can present it to others or companies to prove she owns this game.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;VC game purchase credential with signature&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1670&quot; height=&quot;704&quot; src=&quot;/_astro/did-game-example-with-signature.CetsH4-X_JBsTA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;For example, the game company “SE” that developed &lt;em&gt;First Fantasy&lt;/em&gt;, the game she purchased, has released the next generation game &lt;em&gt;Middle Fantasy&lt;/em&gt;, and the new version isn’t sold on Stream but instead available for digital purchase on “SE“‘s official website. However, buyers can enjoy a 40% discount on &lt;em&gt;Middle Fantasy&lt;/em&gt; by providing proof of purchasing &lt;em&gt;First Fantasy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, since the &lt;code&gt;id&lt;/code&gt; attribute in &lt;code&gt;credentialSubject&lt;/code&gt; records Alice’s DID identity, when “SE“‘s official website confirms that the user is the purchaser recorded in the VC, they can also request the user’s DID signature to ensure they are indeed the purchaser of this purchase proof, not someone who stole it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Requesting purchaser signature before buying game with discount&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1534&quot; height=&quot;640&quot; src=&quot;/_astro/did-game-example-for-discount.CtD_3_58_ZbkDd7.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Next, let’s use this same example to examine the differences between current identity verification mechanisms and DID-based identity verification mechanisms.&lt;/p&gt;
&lt;h2 id=&quot;example-differences-between-current-identity-verification-and-dids&quot;&gt;Example: Differences Between Current Identity Verification and DIDs&lt;/h2&gt;
&lt;p&gt;In the above example, Alice purchased &lt;em&gt;First Fantasy&lt;/em&gt; from the game purchase platform Stream, and the new version &lt;em&gt;Middle Fantasy&lt;/em&gt; is sold digitally on “SE“‘s official website, where anyone who previously purchased the previous version &lt;em&gt;First Fantasy&lt;/em&gt; on Stream can buy &lt;em&gt;Middle Fantasy&lt;/em&gt; at a 40% discount.&lt;/p&gt;
&lt;h3 id=&quot;current-identity-verification-mechanism&quot;&gt;Current Identity Verification Mechanism&lt;/h3&gt;
&lt;p&gt;With current identity verification mechanisms, the Stream game purchase platform would provide a function to log into the Stream platform, typically using a standard like OpenID Connect (OIDC). After connecting to Stream through OIDC on the game’s official website, user purchase information is obtained through Stream’s APIs.&lt;/p&gt;
&lt;p&gt;Let’s examine what problems this method has in terms of autonomy and privacy:&lt;/p&gt;
&lt;h4 id=&quot;autonomy-1&quot;&gt;Autonomy&lt;/h4&gt;
&lt;p&gt;If Stream removes &lt;em&gt;First Fantasy&lt;/em&gt; due to its age, or if there’s a conflict of interest between Alice and Stream (for example, Alice advertises for rival platform Epico) and Stream claims Alice “violated platform regulations” and suspends her account, “SE“‘s official website cannot obtain Alice’s data on Stream through other means.&lt;/p&gt;
&lt;p&gt;This situation is just like when Facebook permanently suspended my account completely without reason—I don’t truly &lt;strong&gt;own&lt;/strong&gt; my digital identity on Facebook.&lt;/p&gt;
&lt;h4 id=&quot;privacy-1&quot;&gt;Privacy&lt;/h4&gt;
&lt;p&gt;When the game’s official website needs to log in through Stream APIs and query purchase records for the &lt;em&gt;Middle Fantasy&lt;/em&gt; discount sale, Stream will learn about Alice’s digital footprint on “SE“‘s official website store. If Stream is also a gaming platform that monetizes user digital footprints (for example, if they provide game advertising), they have a strong incentive to record users’ digital footprints.&lt;/p&gt;
&lt;p&gt;Next, let’s see what the situation would be if W3C DIDs were adopted.&lt;/p&gt;
&lt;h3 id=&quot;w3c-dids-identity-verification-mechanism&quot;&gt;W3C DIDs Identity Verification Mechanism&lt;/h3&gt;
&lt;p&gt;When implementing a purchase proof mechanism using W3C DIDs, when Alice purchases the game &lt;em&gt;First Fantasy&lt;/em&gt;, a game purchase proof in Verifiable Credential format will be issued to Alice based on Alice’s DID identity. This purchase proof will include Stream issuer’s signature, purchaser information, and game information.&lt;/p&gt;
&lt;p&gt;When Alice wants to purchase the new version &lt;em&gt;Middle Fantasy&lt;/em&gt; from “SE“‘s official game platform and needs to verify purchase eligibility on the Stream platform, she only needs to provide that game purchase credential VC to “SE“‘s official website. At that time, “SE“‘s official website will verify whether the credential was issued by Stream, whether it’s a correct game purchase credential, and verify through the purchaser’s signature whether Alice possesses the specific DID identity used during the purchase.&lt;/p&gt;
&lt;p&gt;After verifying the VC-format purchase proof, “SE“‘s game official website can provide the discount to Alice. Let’s again examine autonomy and privacy.&lt;/p&gt;
&lt;h4 id=&quot;autonomy-2&quot;&gt;Autonomy&lt;/h4&gt;
&lt;p&gt;After Stream provides the VC purchase credential to Alice, it will have Stream issuer’s signature on it. This signature is non-repudiable, proving that the Stream issuer definitely signed it.&lt;/p&gt;
&lt;p&gt;The W3C DIDs standard actually provides a revocation mechanism, but this revocation mechanism only allows the issuer to mark this credential as &lt;strong&gt;revoked&lt;/strong&gt; through a &lt;strong&gt;revocation list&lt;/strong&gt;. The signature previously attached to the VC remains non-repudiable.&lt;/p&gt;
&lt;p&gt;Even if Stream marks Alice’s purchase proof as revoked, the purchase information credential that Alice previously saved can still prove that she once purchased this game on Stream, because all the necessary information is in the credential. Although the revocation mechanism will mark this credential as &lt;strong&gt;revoked&lt;/strong&gt;, it cannot deny that the Stream issuer previously signed this credential, so the issuer’s signature on the credential remains valid—it just has an additional &lt;strong&gt;revoked&lt;/strong&gt; mark.&lt;/p&gt;
&lt;p&gt;This way, “SE“‘s official website selling &lt;em&gt;Middle Fantasy&lt;/em&gt; can decide for itself whether to accept such credentials, rather than having all power concentrated with the issuer.&lt;/p&gt;
&lt;h4 id=&quot;privacy-2&quot;&gt;Privacy&lt;/h4&gt;
&lt;p&gt;When Alice provides credentials to the game’s official platform, if Stream chooses to place the issuer’s public key information on the website, at most they can know that someone downloaded the public key information—they won’t know which user is trying to verify which game. If it’s placed on the Ethereum blockchain, Stream won’t even know that someone downloaded the public key information. In terms of privacy protection, this is better than current implementation methods.&lt;/p&gt;
&lt;p&gt;The differences between these two characteristics in traditional verification mechanisms versus DID verification mechanisms are as follows:&lt;/p&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Characteristic&lt;/th&gt;&lt;th&gt;Traditional Identity Verification&lt;/th&gt;&lt;th&gt;W3C DIDs Identity Verification&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Autonomy&lt;/td&gt;&lt;td&gt;Platform has the authority to revoke users’ credentials or identities and refuse any data access&lt;/td&gt;&lt;td&gt;Platform can only mark credentials as revoked but cannot deny credentials it has previously signed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Privacy&lt;/td&gt;&lt;td&gt;When logging in or querying data through APIs, the platform can obtain users’ digital footprints&lt;/td&gt;&lt;td&gt;Platform cannot track users’ digital footprints through login behavior&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;conclusion-privacy-and-autonomy-are-guaranteed-but-whats-still-missing&quot;&gt;Conclusion: Privacy and Autonomy Are Guaranteed, But What’s Still Missing?&lt;/h2&gt;
&lt;p&gt;As stated above, the W3C DIDs and Verifiable Credentials standards do indeed enhance users’ autonomy and privacy regarding identity verification. If this mechanism is so good, we should immediately implement DIDs—what are we waiting for?&lt;/p&gt;
&lt;p&gt;DIDs is a recently formed standard protocol, and there are still many shortcomings. First, if we need better support for DIDs and VCs, we’ll need an app that can store various VC credentials and allow users to select which credential to use through this app when needed. This app will also need to manage users’ private keys. In essence, this app would be very similar to Apple Wallet or Google Wallet—apps used to store tickets and membership cards—but would additionally need to implement functionality for managing internal or external private keys.&lt;/p&gt;
&lt;p&gt;In reality, there isn’t a mature, easy-to-use app to do this. Moreover, since DIDs are still in their early stages, whether to have a VC Wallet first or support DIDs first becomes a chicken-and-egg problem.&lt;/p&gt;
&lt;p&gt;The next issue is &lt;strong&gt;motivation&lt;/strong&gt;. As described above, after adopting DIDs, the power of identity providers and credential issuers will be greatly reduced, and it will be more difficult to track users’ digital footprints. Let’s think from their perspective: if Google or Facebook implementing a new identity verification protocol would significantly reduce advertising precision, thereby decreasing profits from their main revenue source, while also losing more control over users—what motivation would they have to switch to DIDs?&lt;/p&gt;
&lt;p&gt;A better entry point might be from a regulatory perspective, with regulatory authorities like the EU requiring giant corporations to reduce their control over the digital world, or even having governments first adopt the DID standard for official credentials like ID cards or driver’s licenses. I believe this is a better approach.&lt;/p&gt;
&lt;p&gt;Looking back, DIDs is still very early stage, and there are indeed many shortcomings to face. But conversely, it’s also a place full of hope. This standard reflects on the enormous control giant corporations currently have over the digital world and paints a blueprint for a more autonomous and privacy-respecting future, allowing us to consider whether there’s an opportunity to reclaim some power that rightfully belongs to users through standards.&lt;/p&gt;
&lt;p&gt;Of course, our imagination for the future doesn’t have to stop here. We can push further: if we want even better privacy, what solutions are currently available? For example, when verifying whether a user has purchased &lt;em&gt;First Fantasy&lt;/em&gt; on Stream, could we prove that the user indeed purchased the game without even revealing their DID identity?&lt;/p&gt;
&lt;p&gt;The next article will explain how &lt;a href=&quot;https://semaphore.appliedzkp.org/&quot;&gt;Semaphore&lt;/a&gt;, a zero-knowledge proof framework, achieves more advanced privacy applications. Stay tuned!&lt;/p&gt;
&lt;h2 id=&quot;additional-information&quot;&gt;Additional Information&lt;/h2&gt;
&lt;h3 id=&quot;the-problem-of-seamless-key-rotation-in-didweb&quot;&gt;The Problem of Seamless Key Rotation in did:web&lt;/h3&gt;
&lt;p&gt;Luoh Ren-Shan pointed out in a &lt;a href=&quot;https://www.facebook.com/yurenju/posts/pfbid0916c4YdTULXymUW68pE32nuNTYVHAXcpkV4NZEuM7ZodGBHz1NEKpaBgrmLLG6VEl?comment_id=881600443684722&quot;&gt;Facebook comment&lt;/a&gt; that if the issuer Stream adopts &lt;code&gt;did:web&lt;/code&gt; as its DID, the issuer could seamlessly change their key information to invalidate the credential in Alice’s hands.&lt;/p&gt;
&lt;p&gt;This is indeed a problem, but when updating key information this way, other credentials issued by Stream using the original key will also become invalid—it cannot be limited to just Alice’s credential. This would create a crisis of trust for the Stream issuer. As an issuer using &lt;code&gt;did:web&lt;/code&gt;, they would need to weigh the pros and cons before deciding whether to do this. Of course, when a major issue occurs, the issuer might still use this tactic to aggressively handle thorny problems, but compared to traditional methods where results can be easily manipulated, using &lt;code&gt;did:web&lt;/code&gt; is still more trustworthy, though not perfect.&lt;/p&gt;
&lt;p&gt;Looking back, if using &lt;code&gt;did:ethr&lt;/code&gt;, when the DID owner updates key information, a historical record is left, and previous versions of the DID document can be retrieved through &lt;a href=&quot;https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md#versionid-query-string-parameter&quot;&gt;parameter queries&lt;/a&gt;, making it even more trustworthy than &lt;code&gt;did:web&lt;/code&gt;.&lt;/p&gt;</content:encoded><category>Tech</category></item></channel></rss>