<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community</title>
    <description>The most recent home feed on DEV Community.</description>
    <link>https://dev.to</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed"/>
    <language>en</language>
    <item>
      <title>Sell one API call to an agent</title>
      <dc:creator>DAMILARE OLALEYE</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:20:19 +0000</pubDate>
      <link>https://dev.to/dami14_14/sell-one-api-call-to-an-agent-1a4p</link>
      <guid>https://dev.to/dami14_14/sell-one-api-call-to-an-agent-1a4p</guid>
      <description>&lt;p&gt;If an agent needs to buy access to an API, payment and execution need to be tracked separately. This tutorial walks through a test purchase, checks settlement, and reserves one authorized lookup.&lt;/p&gt;

&lt;p&gt;Quote a test purchase, confirm payment, and reserve one authorized execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you will build
&lt;/h2&gt;

&lt;p&gt;A buyer agent purchases one fixed-price lookup and the seller delivers it after payment settles and the seller's own policy permits it. The examples use TypeScript and Test credentials. Your application supplies durable storage, its authorization policy, and the actual lookup.&lt;/p&gt;

&lt;p&gt;You need separate seller and buyer workspaces, a seller test payment account, a 100 USD cents API-call resource, and Test keys with &lt;code&gt;charge:budget&lt;/code&gt;, &lt;code&gt;charge:buy&lt;/code&gt;, and &lt;code&gt;charge:fulfill&lt;/code&gt; for their respective roles. Follow &lt;a href="https://chitmark.com/docs/guides/agent-paid-access#set-up-the-seller-and-buyer" rel="noopener noreferrer"&gt;seller and buyer setup&lt;/a&gt; first. Keep all keys on your servers and use the same environment throughout.&lt;/p&gt;

&lt;p&gt;Install &lt;code&gt;@chitmark/sdk&lt;/code&gt; in a TypeScript project. Set &lt;code&gt;CHITMARK_BUYER_BUDGET_KEY&lt;/code&gt;, &lt;code&gt;CHITMARK_BUYER_KEY&lt;/code&gt;, and &lt;code&gt;CHITMARK_SELLER_FULFILL_KEY&lt;/code&gt; to the corresponding Test keys. Set &lt;code&gt;CHITMARK_SELLER_ID&lt;/code&gt;, &lt;code&gt;CHITMARK_BUYER_ID&lt;/code&gt;, and &lt;code&gt;CHITMARK_RESOURCE_ID&lt;/code&gt; to the IDs from setup, and &lt;code&gt;CHITMARK_OPERATION_ID&lt;/code&gt; to a new, durable ID for this lookup. &lt;code&gt;CHITMARK_API_BASE_URL&lt;/code&gt; is optional and defaults to the production API endpoint. Run the buyer example in your TypeScript runtime; the later snippets are separate steps using the saved state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure a seller and quote a lookup
&lt;/h2&gt;

&lt;p&gt;In the seller workspace, select &lt;strong&gt;Test&lt;/strong&gt; and complete &lt;a href="https://chitmark.com/docs/guides/agent-paid-access#set-up-the-seller-and-buyer" rel="noopener noreferrer"&gt;test payment setup&lt;/a&gt;. Under &lt;strong&gt;Resources&lt;/strong&gt;, create an enabled API-call resource priced at 100 USD cents for one call. Save its ID and both workspace IDs. Test checkout uses the seller's test payment account.&lt;/p&gt;

&lt;p&gt;Use the same server-side values throughout the purchase. Save the lookup inputs, operation ID and digest with the purchase before handing off to checkout. Keep the intent and each mutation's idempotency key stable across retries. A retry uses the same key and exact payload. The examples below use TypeScript. In Python, pass the same request dictionaries to &lt;code&gt;client.charge(...)&lt;/code&gt; and read the same response fields.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set the ceiling and accept&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;createHash&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"node:crypto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Chitmark&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"@chitmark/sdk"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ck_test_"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;" requires a Test key"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chitmark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_API_BASE_URL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"CHITMARK_BUYER_BUDGET_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// charge:budget&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"CHITMARK_BUYER_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// charge:buy&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;sellerTenantId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_SELLER_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;buyerTenantId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_BUYER_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;resourceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_RESOURCE_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Assign and persist this ID in your application before the first request.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;operationId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_OPERATION_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;lookup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;operationDigest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"sha256"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buyerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hex"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"budget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;buyerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"budget:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;quoted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"quote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;operationDigest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"quote:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"purchase"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;quoted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Quote unavailable"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quoted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;"usd"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Unexpected terms"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;quoteVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;maxAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"accept:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"purchase"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Purchase unavailable"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Save the purchase ID and digest in your application.&lt;/span&gt;
&lt;span class="nb"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operationDigest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"pay"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkoutUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Test script only. In your app, pass the URL to the authorized payer.&lt;/span&gt;
  &lt;span class="nb"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkoutUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete test checkout and check capture
&lt;/h2&gt;

&lt;p&gt;Open the returned &lt;code&gt;purchase.checkoutUrl&lt;/code&gt; for the authorized test payer and complete checkout. If &lt;code&gt;next&lt;/code&gt; is &lt;code&gt;wait&lt;/code&gt;, read status for the same purchase instead of starting another. Use status to recover the current checkout URL or payment state after an interruption.&lt;/p&gt;

&lt;p&gt;After checkout, run the status request with the same buyer key and purchase ID. Keep waiting while payment is pending or authorized. Continue only when &lt;code&gt;payment.state&lt;/code&gt; is &lt;code&gt;settled&lt;/code&gt;. A checkout redirect or a Trust Decisions allow carries no payment authorization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check payment&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;purchaseId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"purchase"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Purchase unavailable"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"pay"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkoutUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkoutUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Test script only&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;"settled"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hold fulfillment until payment is settled"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Authorize, reserve, and fulfill one lookup
&lt;/h2&gt;

&lt;p&gt;Run fulfillment on the seller backend using &lt;code&gt;CHITMARK_SELLER_FULFILL_KEY&lt;/code&gt;. Load the saved purchase and operation digest. Check that the authenticated buyer may access this lookup under your own policy. If a Trust Decisions verdict justified this specific permission, include its stored &lt;code&gt;eventId&lt;/code&gt; when you record permission.&lt;/p&gt;

&lt;p&gt;Persist a unique execution ID before requesting the reservation. The example uses an application-provided &lt;code&gt;deliverOnce&lt;/code&gt; function for the actual lookup. Implement it so the output or business effect and the execution ID commit together. Reuse the ID on retry. If you lose the reserve response, read the current purchase and reconcile instead of executing without a fresh granted lease.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reserve and report usage&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;seller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"CHITMARK_SELLER_FULFILL_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// charge:fulfill&lt;/span&gt;
&lt;span class="c1"&gt;// Application values loaded from durable state after checking local policy.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;localPermission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Lookup not authorized"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"permission"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"permission:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;executionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;reserved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"reserve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;executionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;operationDigest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"reserve:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;executionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"purchase"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;"settled"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;granted&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executionId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="n"&gt;executionId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leaseUntil&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hold delivery"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deliverOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;executionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;leaseUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leaseUntil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sellerTenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;purchaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;executionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;usedUnits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"delivered"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"usage:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;executionId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;":1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verify and recover
&lt;/h2&gt;

&lt;p&gt;Read the purchase with the buyer key or find it under &lt;strong&gt;Agent Paid Access → Purchases&lt;/strong&gt; in the seller workspace. Confirm the execution is delivered and has one used unit. Try fulfilling before settlement and with local permission denied: both must hold delivery.&lt;/p&gt;

&lt;p&gt;Persist the operation ID, inputs, digest, purchase ID, and execution ID before their respective steps. Retry a lost request with the same idempotency key and exact payload. If the reservation response is lost, inspect and reconcile the purchase instead of delivering without a fresh granted lease. If delivery is uncertain, keep the units reserved and reconcile before retrying. If usage reporting fails after delivery, retry the same usage payload.&lt;/p&gt;

&lt;p&gt;The fulfillment example is a server-side integration fragment: implement &lt;code&gt;localPermission&lt;/code&gt; and &lt;code&gt;deliverOnce&lt;/code&gt; in your application. &lt;code&gt;deliverOnce&lt;/code&gt; must durably deduplicate by execution ID and enforce the lease at the execution boundary. Refunds and disputes can change payment state after settlement. See the &lt;a href="https://chitmark.com/docs/api/charge" rel="noopener noreferrer"&gt;charge reference&lt;/a&gt; for operations and scopes, and the &lt;a href="https://chitmark.com/docs/guides/agent-paid-access" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt; for live setup.&lt;/p&gt;




&lt;p&gt;Read the full guide on &lt;a href="https://chitmark.com/docs/guides/sell-api-call/" rel="noopener noreferrer"&gt;Chitmark&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>stripe</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Future directions of travel</title>
      <dc:creator>Dan Walsh</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:18:54 +0000</pubDate>
      <link>https://dev.to/dang-w/future-directions-of-travel-cki</link>
      <guid>https://dev.to/dang-w/future-directions-of-travel-cki</guid>
      <description>&lt;p&gt;I already put this in &lt;a href="https://dev.to/log"&gt;the log&lt;/a&gt;, but whatever. Free will n all that, I'm double posting.&lt;/p&gt;

&lt;p&gt;Been thinking about the future of SWE and agentic use in general (shocker, who working in SW hasn't?)&lt;/p&gt;

&lt;p&gt;In my eyes: verification and governance.&lt;/p&gt;

&lt;p&gt;My prediction on SWE directions: verification engineering becoming a massive discipline/the new standard for software engineering at large.&lt;/p&gt;

&lt;p&gt;We're no longer hand crafting pieces of curated, artisanal code to try and solve problems.&lt;/p&gt;

&lt;p&gt;Aside: people sometimes seem to forget solving problems was the point of the job in the end - writing code in and of itself was not the full job, but many people seem to have made it their personality or their measure of value/impact as an engineer, and are now struggling with their identity as a result, but that's a different thread.&lt;/p&gt;

&lt;p&gt;I understand the tension here. Hand writing code gave many of us the level of scrutiny that allowed for an ongoing understanding and verification in terms of the code produced, but as the be all and end all of a given engineer's identity, it's now far too limiting.&lt;/p&gt;

&lt;p&gt;We're now at the factory's production line, and our job is to assess which of the different experiments and approaches output by an agentic session best address a given problem, which is most extensible and/or maintainable for the future and its problems to address, and to provide a level of confidence and rigour to how we arrived at that decision.&lt;/p&gt;

&lt;p&gt;How do we do that? With the necessary guardrails, assessments, and verification practices in place.&lt;/p&gt;

&lt;p&gt;Zoom out, same problem appears at a bigger scale. Verification is governance at the scale of a PR; governance is verification at the scale of an organisation.&lt;/p&gt;

&lt;p&gt;Governance.&lt;/p&gt;

&lt;p&gt;Not the sexiest option by a mile, but it feels like the right route, because we're slowly (or quickly depending on your personal perceptions and p(doom)) offloading our cognitive capabilities to a subscription service.&lt;/p&gt;

&lt;p&gt;Intelligence and aptitude on demand, where we need to pay a given value each month to be in with a fighting chance in the ongoing arms race of individual capability.&lt;/p&gt;

&lt;p&gt;I'm convinced that, of all the AI safety risks we need to guard against, gradual disempowerment and over-reliance are far too easily overlooked in favour of misuse, for example. Misuse / CBRN applications are obviously terrifying, and real problems, but the insidiousness of disempowerment is the killer to me.&lt;/p&gt;

&lt;p&gt;In X industry, Y organisation is so much further ahead than us! We need to use AI to catch up. We don't have time to spend dwelling on these decisions and problems - DecisionBot 9000, what's your suggestion here? Ok great, implement that.&lt;/p&gt;

&lt;p&gt;Fast forward Z months/weeks/days later - I don't understand any of this. Where are we? Let's ask AI - it's best informed and capable to consume the information we have here, get its assessment and then we'll go with its recommendations.&lt;/p&gt;

&lt;p&gt;At what point do we recognise the problem that's developed? How do we even begin to pull ourselves out of that hole? Do we even recognise we're boiling along with the other frogs?&lt;/p&gt;

&lt;p&gt;We need governance in place to try and offset these situations at the earliest possible points. In practice: named human(s) owning each significant decision, with the ability to explain it without asking a model, and recording why a given recommendation was accepted, not just that it was.&lt;/p&gt;

&lt;p&gt;I don't wanna be a dang frog.&lt;/p&gt;

</description>
      <category>thoughts</category>
      <category>softwareengineering</category>
      <category>future</category>
      <category>ai</category>
    </item>
    <item>
      <title>I cut my CI wait from 25 minutes to about 12 and checked that no test was dropped</title>
      <dc:creator>Miguel Shinyenyi</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:18:16 +0000</pubDate>
      <link>https://dev.to/miguel_shinyenyi_e2291c8c/i-cut-my-ci-wait-from-25-minutes-to-about-12-and-checked-that-no-test-was-dropped-3n25</link>
      <guid>https://dev.to/miguel_shinyenyi_e2291c8c/i-cut-my-ci-wait-from-25-minutes-to-about-12-and-checked-that-no-test-was-dropped-3n25</guid>
      <description>&lt;h2&gt;
  
  
  The wait
&lt;/h2&gt;

&lt;p&gt;umwayi-os is a Python command line with a large test suite. It has more than 2,000 tests. They run on every pull request, on Python 3.10, 3.11, 3.12 and 3.13. The core uses only the standard library, so the tests start real child processes in temporary folders. That makes them thorough and slow. The code is public: &lt;a href="https://github.com/Miguel-Shinyenyi/umwayi-os" rel="noopener noreferrer"&gt;https://github.com/Miguel-Shinyenyi/umwayi-os&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On Nov 12 I measured one job on one pull request: 24.9 minutes. Each job ran the whole suite, and one push could start two runs of four jobs each. The tests alone took about 1,810 seconds on Python 3.11.&lt;/p&gt;

&lt;p&gt;I build this project with several AI builders working in parallel. Each pull request is reviewed and then merged. A 25 minute wait on each push slows every round of review.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before: one push
-------------------------
push
 +- run 1: 4 jobs
 +- run 2: 4 jobs
each job: all tests
each job: about 25 min
-------------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: stop running the same thing twice
&lt;/h2&gt;

&lt;p&gt;The first change was small (pull request 59). CI ran on pull requests only, and a newer push cancelled the older run. One push now means one run of four jobs. I also cached the npm download. That saved little: the whole Node step was 0.4 minutes of a 24.9 minute job. I cached it anyway, and I wrote the number in the pull request.&lt;/p&gt;

&lt;p&gt;This change cut the number of runs. It did not shorten one run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: do not run what a change cannot affect
&lt;/h2&gt;

&lt;p&gt;Most pull requests do not touch most of the code. A change to a documentation page cannot break a test that never reads that page. But "cannot" has to be proven, not assumed.&lt;/p&gt;

&lt;p&gt;I wrote a map. For every test file, the map lists which paths outside its own area the test reads. A script scans the test files and fails when a test reads a path the map does not list. The map is data in &lt;code&gt;tools/ci_map.json&lt;/code&gt;, and &lt;code&gt;tests/test_ci_map.py&lt;/code&gt; keeps it true.&lt;/p&gt;

&lt;p&gt;The scan corrected my own guesses. I had estimated that 27 test files touch the adapters folder. The scan found 43. I had estimated 10 touch the &lt;code&gt;.kiro&lt;/code&gt; folder. Only 4 read it. The rest only mention it in a path inside a temporary folder. Only 23 of 115 test files read anything outside &lt;code&gt;tests/&lt;/code&gt; and &lt;code&gt;umwayi/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A second script, the plan, reads the changed paths of a pull request and decides which jobs run. Its rules are strict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;changed path
   |
   v
anything unusual?
   unknown path
   odd path
   change under .github/ or tools/
   push to main
   |
   +-- yes: run everything
   |
   v
no: use the longest matching
route in the map
   |
   v
whole suite, some test files,
or none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default is to run everything. The filter only narrows the run when it can prove the narrowing is safe. A push to main always runs all four Python versions, so a wrong filter is caught within one merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: split the rest into three shards
&lt;/h2&gt;

&lt;p&gt;Each test job still ran the whole suite. I split the test files into three shards per Python version. I measured the seconds of every test file and balanced the three lists by those seconds. The lists live in &lt;code&gt;tools/ci_shards.json&lt;/code&gt;, and one command rewrites them from the measurements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;one job   ##############################
shard 1   ##########
shard 2   ##########
shard 3   ##########
          each # is about 60 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One job took 1,810 seconds of test time. Each shard takes about 603 seconds. The three shards run at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: prove that nothing was dropped
&lt;/h2&gt;

&lt;p&gt;Splitting creates a new way to fail. A shard can skip a test file and still report green. If a plan leaves out a job, a skipped job looks like a pass. I wanted neither.&lt;/p&gt;

&lt;p&gt;So I added one check that always runs, last, named &lt;code&gt;result&lt;/code&gt;. It is the only check a branch rule needs to require. It fails when any of these is true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;the plan job failed
a planned job was skipped
a planned job was cancelled
a shard wrote no report
a shard reports a test that did
  not start
two shards disagree about which
  tests exist
a test file is in no shard
the tests that ran are not all the
  tests found in the selected files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tested the check with planted faults. One test makes a shard drop a test that never starts. Another adds a test file to no shard. Both must turn &lt;code&gt;result&lt;/code&gt; red, and both do. The summary of a green run also lists what it did not run, with the reason. What the plan left out runs on main after the merge.&lt;/p&gt;

&lt;p&gt;I did not trust the check until I saw it fail on purpose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final result
   |
   v
every planned job passed?
every shard reported?
every test found also ran?
   |
   +-- no to any: red
   |
   v
yes to all: green, with a list of
anything not run and why
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: the same filter on a laptop
&lt;/h2&gt;

&lt;p&gt;The builders did not need CI to tell them what to run. &lt;code&gt;tools/affected_tests.py&lt;/code&gt; reads what differs from main and asks the same function as the CI plan, with the same map. A test proves it prints the same plan as CI for the same changed files. While building, a builder runs only the affected tests. The whole suite runs only when the tool prints &lt;code&gt;FULL SUITE&lt;/code&gt;. GitHub CI stays the record.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I measured after
&lt;/h2&gt;

&lt;p&gt;I read the run times from the Actions page for pull requests 73 to 89.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A documentation only pull request: 1 minute 30 seconds for its first run.&lt;/li&gt;
&lt;li&gt;Pull requests that run the whole Python suite: 11 minutes 22 seconds to 12 minutes 4 seconds in the typical case.&lt;/li&gt;
&lt;li&gt;Heavier runs: 13 to 22 minutes, on pull requests 73, 80, 83, 84, 85 and 88. I checked these on GitHub. The extra time is waiting: when several runs overlap, their jobs wait for a free runner before they start.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before, one job took 24.9 minutes. A typical full run now takes about 12. That is the 25 to 12 in the title.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do not know yet
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I did not measure total runner minutes. Three shards per version repeat setup work, so the total may be the same or higher. The wait fell. The cost may not have.&lt;/li&gt;
&lt;li&gt;I cannot run the workflow file on my machine. A test pins its text, and the real run on GitHub is the record.&lt;/li&gt;
&lt;li&gt;The affected-only run can miss a test that reads a path built from data, or a path a child process reads from its working directory. The scanner cannot see those. A change inside &lt;code&gt;umwayi/&lt;/code&gt; runs the whole Python suite for that reason.&lt;/li&gt;
&lt;li&gt;The four old check names no longer exist. A branch rule that requires them waits forever. I have to change that rule by hand, and I have not yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I took from it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Measure before you guess. My counts of which tests touch which folders were wrong by a wide margin, and the scan fixed them.&lt;/li&gt;
&lt;li&gt;A filter that cannot prove it is safe should run everything.&lt;/li&gt;
&lt;li&gt;Splitting a suite adds a failure you cannot see: a shard that drops a test and still reports green. Add a check that compares the tests found with the tests run.&lt;/li&gt;
&lt;li&gt;A skipped job is not a pass. Say what was skipped and why.&lt;/li&gt;
&lt;li&gt;Test your check by breaking things on purpose, and watch it go red.&lt;/li&gt;
&lt;li&gt;Time spent waiting for a runner is not time spent running. With several builders pushing at once, runs overlap and queue, so a typical run time understates the wait.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://miguel-shinyenyi.github.io/miguel-site/tech/the-ci-wait-halved/" rel="noopener noreferrer"&gt;my site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>testing</category>
      <category>ci</category>
      <category>buildinginpublic</category>
    </item>
    <item>
      <title>A Shopify CSV checker with line-level reports and an n8n import gate</title>
      <dc:creator>didyouseethis212-sys</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:17:57 +0000</pubDate>
      <link>https://dev.to/didyouseethis212sys/a-shopify-csv-checker-with-line-level-reports-and-an-n8n-import-gate-2p2f</link>
      <guid>https://dev.to/didyouseethis212sys/a-shopify-csv-checker-with-line-level-reports-and-an-n8n-import-gate-2p2f</guid>
      <description>&lt;p&gt;Disclosure: I maintain Catalog Import Guard, including its paid API. This article was prepared with AI assistance, and the sample results and workflow execution were checked before publication.&lt;/p&gt;

&lt;p&gt;A product CSV can be valid CSV and still contain an accidental duplicate variant, a price field with a currency symbol, or an empty field that changes an existing value during an overwrite. I built a small checker around that pre-import step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://catalog-import-guard.mayasmile.workers.dev/try" rel="noopener noreferrer"&gt;Try the browser checker&lt;/a&gt;&lt;/strong&gt; — no account, API key or Shopify installation is required. The CSV is checked on your device.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example you can reproduce
&lt;/h2&gt;

&lt;p&gt;Load the built-in example, or paste this CSV and choose &lt;strong&gt;Update products&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;URL handle,Title,Option1 name,Option1 value,Price,Vendor
linen-shirt,Linen Shirt,Size,S,49.00,
linen-shirt,,,S,$39.00,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The report contains two errors and one warning:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Physical line&lt;/th&gt;
&lt;th&gt;Finding&lt;/th&gt;
&lt;th&gt;Why it needs review&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Blank Vendor overwrite warning&lt;/td&gt;
&lt;td&gt;With overwrite enabled, an empty vendor can clear an existing value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Duplicate variant&lt;/td&gt;
&lt;td&gt;Size S already appears within the same product handle.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Price format&lt;/td&gt;
&lt;td&gt;The price field expects a number without a currency symbol.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The checker reports physical line numbers, including files with quoted multiline cells. It does not guess what a price should be or change a store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the same check in n8n
&lt;/h2&gt;

&lt;p&gt;For a recurring supplier-file handoff, the &lt;a href="https://github.com/didyouseethis212-sys/catalog-csv-import-gate-n8n" rel="noopener noreferrer"&gt;public workflow and setup guide are on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The workflow runs two synthetic cases, sends CSV text to the API, validates the response shape, produces a downloadable CSV issue report for each item, and routes blocking findings separately from results ready for manual review.&lt;/p&gt;

&lt;p&gt;An HTTP 200 response alone does not mean the catalog passed. Errors, failed checks or a truncated report go to the blocked branch. A passing, untruncated result goes to the review branch. Both branches are connected; neither imports products or sends messages.&lt;/p&gt;

&lt;p&gt;Import and execution were verified in local n8n 2.46.6 using the actual Worker handler through a localhost fixture and synthetic authentication. Both branches and the binary report filenames were checked. I have not tested this in n8n Cloud or through a real Shopify import.&lt;/p&gt;

&lt;h2&gt;
  
  
  Costs, data and limits
&lt;/h2&gt;

&lt;p&gt;The browser checker remains free and local. The n8n workflow requires your own RapidAPI key and sends CSV text to the API. Remove customer information and credentials first.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://rapidapi.com/didyouseethis212sys/api/catalog-import-guard/pricing" rel="noopener noreferrer"&gt;current API plans&lt;/a&gt; include BASIC at $0 for 100 requests/month and PRO at $5 for 1,000 requests/month, subject to platform terms, request limits and bandwidth fees. The two-case tutorial makes two requests per run. Your n8n hosting can have separate costs.&lt;/p&gt;

&lt;p&gt;The browser accepts UTF-8 CSV text up to 256 KiB and 5,000 rows. API requests have a 256 KiB encoded JSON limit, so JSON escaping also counts. Checks cover selected product CSV fields; a passing result does not guarantee Shopify accepts an import. Review overwrite warnings and Shopify's own import preview before importing.&lt;/p&gt;

&lt;p&gt;If you handle supplier CSVs, which errors take the most manual checking? A synthetic row and the relevant column names are enough to discuss a case; please do not post private catalog or customer data.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>shopify</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Recognize an agent in your API</title>
      <dc:creator>DAMILARE OLALEYE</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:17:52 +0000</pubDate>
      <link>https://dev.to/dami14_14/recognize-an-agent-in-your-api-fcm</link>
      <guid>https://dev.to/dami14_14/recognize-an-agent-in-your-api-fcm</guid>
      <description>&lt;p&gt;When an agent calls your API, knowing whether it has been seen before can help your application provide continuity. This tutorial shows how to resolve an agent proof and handle the result in a server-side endpoint.&lt;/p&gt;

&lt;p&gt;Resolve an incoming agent proof and handle recognized, unknown, and unavailable identity evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you will build
&lt;/h2&gt;

&lt;p&gt;Add a server-side endpoint that resolves an incoming agent proof and returns a different response for recognized agents, unknown visitors, and unavailable identity evidence. Attribution provides evidence for your application's access policy; recognition alone does not authorize an action.&lt;/p&gt;

&lt;p&gt;You need Node.js or Python, a Chitmark workspace with Attribution enabled, a Test key with &lt;code&gt;attribution:read&lt;/code&gt;, and your site's exact public HTTPS origin. To test recognition, you also need an enrolled agent and a fresh proof for that site. The &lt;a href="https://chitmark.com/docs/guides/agent-attribution-network" rel="noopener noreferrer"&gt;two-website example&lt;/a&gt; walks through enrollment and signing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the SDK and configure your site
&lt;/h2&gt;

&lt;p&gt;Use SDK version 0.9.0 or later for network proofs. Create a Test API key with &lt;code&gt;attribution:read&lt;/code&gt; in your site's workspace. Set &lt;code&gt;CHITMARK_API_KEY&lt;/code&gt; on the server and set &lt;code&gt;CHITMARK_SITE&lt;/code&gt; to your exact public HTTPS origin, for example &lt;code&gt;https://app.example.com&lt;/code&gt; without a trailing slash. The SDK uses &lt;code&gt;https://api.chitmark.com&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;Give the visiting agent your workspace ID, recipient key record ID, origin, environment, purpose and data mode. Keep the bearer credential on your server. The agent sends a fresh &lt;code&gt;Chitmark-Agent-Proof&lt;/code&gt; header for those values. The defaults are &lt;code&gt;identity_attribution&lt;/code&gt; and &lt;code&gt;hashed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm install @chitmark/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python -m pip install chitmark flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add an endpoint
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;CHITMARK_API_KEY&lt;/code&gt; to your Test read key and &lt;code&gt;CHITMARK_SITE&lt;/code&gt; to your public HTTPS origin, such as &lt;code&gt;https://app.example.com&lt;/code&gt;. Save the Node.js example as &lt;code&gt;attribution.mjs&lt;/code&gt; or the Python example as &lt;code&gt;attribution.py&lt;/code&gt;. The server listens on &lt;code&gt;127.0.0.1:3000&lt;/code&gt;. Its configured site is used for resolution, not a client-supplied Host header.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;node attribution.mjs&lt;/code&gt; or &lt;code&gt;python attribution.py&lt;/code&gt;. Then run &lt;code&gt;curl http://127.0.0.1:3000/agent-task&lt;/code&gt; without a proof. You should see &lt;code&gt;Unknown visitor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;createServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"node:http"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Chitmark&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ChitmarkError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"@chitmark/sdk"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;site&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_SITE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_API_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Configure CHITMARK_SITE and CHITMARK_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;piiMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_ATTRIBUTION_PII_MODE&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"raw"&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"raw"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hashed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;chitmark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chitmark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;piiMode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;"/agent-task"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Cache-Control"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"no-store"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;chitmark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CHITMARK_FIXTURE_LOG&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recognized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nb"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recognized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Unknown visitor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"previously_verified"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
          &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"Recognized agent; verified principal; email unavailable"&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Recognized agent; verified principal; email authorized"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Recognized agent; principal unavailable"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;ChitmarkError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Identity evidence unavailable"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chitmark&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;Chitmark&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ChitmarkError&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;site&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CHITMARK_SITE"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;pii_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"raw"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"CHITMARK_ATTRIBUTION_PII_MODE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"raw"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s2"&gt;"hashed"&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Chitmark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"CHITMARK_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pii_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pii_mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/agent-task"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;agent_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Cache-Control"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"no-store"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nc"&gt;ChitmarkError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Identity evidence unavailable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;

    &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"identity"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;principal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"principal"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"recognized"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Unknown visitor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"previously_verified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;"Recognized agent; verified principal; email unavailable"&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s2"&gt;"Recognized agent; verified principal; email authorized"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Recognized agent; principal unavailable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exercise each result
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Expected behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No proof and no separate session evidence&lt;/td&gt;
&lt;td&gt;The endpoint returns &lt;code&gt;Unknown visitor&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fresh proof for this site from an enrolled agent&lt;/td&gt;
&lt;td&gt;The agent is recognized. Principal details can still be withheld.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recognized agent with a disclosure grant&lt;/td&gt;
&lt;td&gt;The principal can be previously verified; email can still be unavailable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attribution service unavailable&lt;/td&gt;
&lt;td&gt;The endpoint returns 503; do not treat the failure as recognition.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use the &lt;a href="https://chitmark.com/docs/guides/agent-attribution-network" rel="noopener noreferrer"&gt;two-website example&lt;/a&gt; to generate a fresh proof for the exact recipient, environment, purpose, and data mode, then include it in the &lt;code&gt;Chitmark-Agent-Proof&lt;/code&gt; header. Repeat with a proof for another site or a revoked binding and check the unknown path. Test failures by temporarily making the service unreachable in a test environment.&lt;/p&gt;

&lt;p&gt;Use the site's scoped &lt;code&gt;identity.subject_id&lt;/code&gt; for continuity, and apply your own authorization before protected work. Keep API keys, proof headers, and personal data out of logs. Email disclosure requires the appropriate grant, consent, plan, scope, and raw mode; see the &lt;a href="https://chitmark.com/docs/guides/agent-attribution#read-the-result" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Read the full guide on &lt;a href="https://chitmark.com/docs/guides/recognize-agent-api/" rel="noopener noreferrer"&gt;Chitmark&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What to check before buying a ready-made admin panel template</title>
      <dc:creator>Mehedi Mansur Rafi</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:17:19 +0000</pubDate>
      <link>https://dev.to/mehedirafi/what-to-check-before-buying-a-ready-made-admin-panel-template-1p6e</link>
      <guid>https://dev.to/mehedirafi/what-to-check-before-buying-a-ready-made-admin-panel-template-1p6e</guid>
      <description>&lt;p&gt;Part 1 of Before You Buy Code.&lt;/p&gt;

&lt;p&gt;I build admin panels for clinic and small business sites, and I have bought templates to save time. Two of them cost me more time than they saved. The screenshots were fine. The faults sat in parts a screenshot cannot show: a login with no roles behind it, a package with half the pages from the sales page, and setup docs that stopped before the first error.&lt;/p&gt;

&lt;p&gt;Now I run the same checks on every Laravel admin panel template before I pay. Each check has a good sign and a red flag, and most take minutes with a demo or a file list. At the end I run the list on AdminForge, the kit I sell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 1: log in, then log in as someone with fewer rights
&lt;/h2&gt;

&lt;p&gt;Open the demo and sign in as admin. Create a second account with a staff role, sign in as that account, and open a settings page by typing its address.&lt;/p&gt;

&lt;p&gt;Good sign: the second account sees fewer pages, and the server refuses the admin pages at the typed address.&lt;/p&gt;

&lt;p&gt;Red flag: the sales page lists roles, and the demo has one login that opens everything. A menu that hides links is decoration. When the second account can open the user list by address, permissions are missing, and adding them later means touching every page.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Check 2: count the Blade files and open the layout
&lt;/h2&gt;

&lt;p&gt;Ask for the file list, or open the package and count the files in resources/views. The count tells you how much of the panel is real pages. A sales page can show thirty screens that turn out to be ten views in different colors.&lt;/p&gt;

&lt;p&gt;Then open the main layout file. Good sign: the sidebar and the top bar sit in the layout once, and each page fills the middle. Red flag: the menu code is pasted into every view. With a pasted menu, one menu change becomes the same edit repeated across twenty files.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Check 3: look for migrations and run them
&lt;/h2&gt;

&lt;p&gt;Open database/migrations. Good sign: files exist for the tables the panel needs, users, roles, settings, and the rest, and &lt;code&gt;php artisan migrate&lt;/code&gt; builds them on a throwaway database with no errors.&lt;/p&gt;

&lt;p&gt;Red flag: the setup guide starts with "import this SQL file", and no migrations ship. A dump ties your project to the seller's test data. A second mismatch: HTML screens only, with no migrations, sold under copy that calls the package a complete admin system. An HTML kit is fair when the listing sells it as one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 4: seed the database and look at full pages
&lt;/h2&gt;

&lt;p&gt;Check database/seeders, then run &lt;code&gt;php artisan db:seed&lt;/code&gt;. Good sign: seeding creates a demo admin account, some users, and sample rows in the main tables, and the docs print the demo login.&lt;/p&gt;

&lt;p&gt;Red flag: no seeders ship at all. Every list page opens empty, so you cannot tell an empty table from a broken query, and the first day goes to typing test rows by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 5: read the documentation before the code
&lt;/h2&gt;

&lt;p&gt;Read the install guide from the top. Good sign: it lists the server requirements, the install commands in order, a page list, and the first changes every buyer makes, adding a menu item, changing the logo or colors. The screenshots in the docs show the version the package installs.&lt;/p&gt;

&lt;p&gt;Red flag: the whole documentation is one short readme that ends at the install command. When setup fails at step three, a thin readme leaves you searching the web for an answer the seller should have written down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 6: read composer.json and match it against your server
&lt;/h2&gt;

&lt;p&gt;Open composer.json and read the require section. It names the PHP version and the laravel/framework version the kit was built for. Laravel 11 and 12 both need PHP 8.2 or above. Run &lt;code&gt;php -v&lt;/code&gt; on your server, or read the version in your hosting panel, and compare before you pay.&lt;/p&gt;

&lt;p&gt;Good sign: the listing states the versions and composer.json agrees. Red flag: the listing says the kit works with the latest Laravel, and composer.json pins an old major version. Treat a missing composer.json the same way when the kit calls itself a Laravel package.&lt;/p&gt;

&lt;p&gt;Once the panel is in your app, the app still has to go online. My earlier post on putting a Laravel website online covers the server side: &lt;a href="https://dev.to/mehedirafi/how-to-put-a-laravel-website-online-step-by-step-3oif"&gt;https://dev.to/mehedirafi/how-to-put-a-laravel-website-online-step-by-step-3oif&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 7: find the licence and answer three questions from it
&lt;/h2&gt;

&lt;p&gt;Find the licence file in the package, or the terms on the listing, and answer three questions from the text. Can you use the template in a client project? How many projects does one purchase cover? Can you charge the client for the finished site?&lt;/p&gt;

&lt;p&gt;Good sign: the licence answers all three in plain lines. Red flag: no licence file exists anywhere, or the terms allow one personal project while the sales page shows the kit inside client work. Buyers skip this check more than any other, and it is the one that can turn a paid template into an argument with your own client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 8: check the update history and the questions under the listing
&lt;/h2&gt;

&lt;p&gt;Find the changelog or the release dates. Good sign: a release within the last few months that fixes bugs or follows a Laravel release, and an update window stated in the price.&lt;/p&gt;

&lt;p&gt;Then read the public questions under the listing. Sellers who support their work answer in the open. Red flag: the last update landed two Laravel versions ago, and the newest questions sit unanswered with bug reports in them.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 15 minute test when a live demo exists
&lt;/h2&gt;

&lt;p&gt;Work through the demo in this order. Sign in. Open every item in the menu and note any page that errors. Save one setting and check that it stays saved. Open an invoice page and print it. Create the low role account from Check 1 and revisit one admin page.&lt;/p&gt;

&lt;p&gt;When no demo exists, read the file list against the page list twice, then send the seller the two questions the listing leaves open. The reply tells you a lot about the support from Check 8 before money moves.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The same list, run on my own kit
&lt;/h2&gt;

&lt;p&gt;AdminForge is my own product, so read this part as a seller showing his work. The listing states 34 Blade files and names the main pages: login, roles, settings, and invoice pages. Check 1 and Check 2 tell you to open those pages and count those files against the claim.&lt;/p&gt;

&lt;p&gt;AdminForge is a UI kit, and you connect the Blade views to your own app. That puts the database checks from this list on your side: your migrations, your seeders, your data.&lt;/p&gt;

&lt;h2&gt;
  
  
  A score sheet you can reuse
&lt;/h2&gt;

&lt;p&gt;Copy these lines into a note and mark each pass or fail:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A low role account is blocked from admin pages by the server&lt;/li&gt;
&lt;li&gt;Blade file count matches the page list on the sales page&lt;/li&gt;
&lt;li&gt;Migrations ship with the package and run clean on a test database&lt;/li&gt;
&lt;li&gt;Seeders fill the main tables, and the docs print the demo login&lt;/li&gt;
&lt;li&gt;Documentation covers install, the page list, and first changes&lt;/li&gt;
&lt;li&gt;composer.json versions match the listing and your server&lt;/li&gt;
&lt;li&gt;The licence allows client work and states the project count&lt;/li&gt;
&lt;li&gt;A recent release exists, and listing questions get answers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AdminForge is my own Blade admin kit. It has 34 Blade files, with login, roles, settings, and invoice pages. It is a UI kit, so you connect it to your own app. The listing says exactly what is inside: &lt;a href="https://mehedirafi.gumroad.com/l/adminforge" rel="noopener noreferrer"&gt;https://mehedirafi.gumroad.com/l/adminforge&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I am Mehedi Mansur Rafi, a freelance Laravel developer (B.Sc. in Computer Science &amp;amp; Engineering). I build hospital, clinic, and small business websites. CarePoint Admin is my admin kit for clinic work: &lt;a href="https://mehedirafi.gumroad.com/l/carepoint-admin" rel="noopener noreferrer"&gt;https://mehedirafi.gumroad.com/l/carepoint-admin&lt;/a&gt;. My full store is at &lt;a href="https://mehedirafi.gumroad.com/" rel="noopener noreferrer"&gt;https://mehedirafi.gumroad.com/&lt;/a&gt; and my site is &lt;a href="https://mehedimansurrafi.online" rel="noopener noreferrer"&gt;https://mehedimansurrafi.online&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>AgentedSEO Review: A WordPress SEO Plugin Your AI Agent Can Run</title>
      <dc:creator>SoloAgentFlow</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:17:16 +0000</pubDate>
      <link>https://dev.to/fun_fun_19313eced54af3c68/agentedseo-review-a-wordpress-seo-plugin-your-ai-agent-can-run-3039</link>
      <guid>https://dev.to/fun_fun_19313eced54af3c68/agentedseo-review-a-wordpress-seo-plugin-your-ai-agent-can-run-3039</guid>
      <description>&lt;p&gt;AI agents can already write and publish WordPress posts. The weak spot has been SEO: once an agent starts editing titles and meta descriptions behind the scenes, you lose track of what it changed and why. AgentedSEO is a plugin built to close that gap. Here is what it does, what the launch deal costs, and three realistic ways to turn it into paid work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AgentedSEO gives AI agents their own WordPress login limited to SEO-only rights.&lt;/li&gt;
&lt;li&gt;Every agent change shows before and after, needs approval on live pages, and can be undone.&lt;/li&gt;
&lt;li&gt;The founder reports a first $129 sale two hours after posting the launch.&lt;/li&gt;
&lt;li&gt;Launch lifetime pricing runs from $49 to $199 and, per the founder, closes December 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this plugin exists
&lt;/h2&gt;

&lt;p&gt;The founder runs a WordPress agency in Pune and builds plugins on the side. The idea came from the founder's own site, where an AI agent already writes and publishes the posts. For SEO, though, the agent still needed a second plugin, and when it edited meta data through the WordPress REST API, the founder says there was no way to see what it had changed.&lt;/p&gt;

&lt;p&gt;That is a familiar problem for anyone automating content. An agent that silently rewrites a live page's SEO fields is a liability, not a time saver. So the founder built an SEO plugin where the agent is treated as a first-class user instead of a hidden script.&lt;/p&gt;

&lt;h2&gt;
  
  
  How AgentedSEO works
&lt;/h2&gt;

&lt;p&gt;The setup is designed around trust and visibility. Here is what the founder describes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One-URL connection:&lt;/strong&gt; Claude, Cursor, Codex or Hermes connect to the site with a single URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A dedicated agent login:&lt;/strong&gt; the agent gets its own WordPress account with SEO-only rights, so it cannot touch the rest of the site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Before-and-after view:&lt;/strong&gt; every change the agent makes shows the old and new version side by side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval gate on live pages:&lt;/strong&gt; if a page is already published, the change waits for a human to approve it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Undo:&lt;/strong&gt; changes can be rolled back later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual mode:&lt;/strong&gt; underneath, it is a normal SEO plugin, so people who never use an agent can run it by hand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point is easy to overlook. It means you are not betting a client site on an experimental agent-only tool. If the agent workflow does not fit a project, the plugin still works the traditional way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compared to the usual setup
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Agent editing meta via REST&lt;/th&gt;
&lt;th&gt;AgentedSEO with an agent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Agent permissions&lt;/td&gt;
&lt;td&gt;Depends on the account it uses&lt;/td&gt;
&lt;td&gt;Own login, SEO-only rights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seeing what changed&lt;/td&gt;
&lt;td&gt;Hard to track, per the founder&lt;/td&gt;
&lt;td&gt;Before and after for every change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changes to live pages&lt;/td&gt;
&lt;td&gt;Applied directly&lt;/td&gt;
&lt;td&gt;Wait for approval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rolling back&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Built-in undo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works without an agent&lt;/td&gt;
&lt;td&gt;Needs a separate SEO plugin&lt;/td&gt;
&lt;td&gt;Yes, runs as a normal SEO plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Pricing and launch traction
&lt;/h2&gt;

&lt;p&gt;The founder is selling lifetime licenses during launch, priced from $49 to $199, with the offer closing on December 1. One tier mentioned is a 25-site plan at $129. Plan details beyond that were not shared, so check the official site for current pricing and what each tier includes.&lt;/p&gt;

&lt;p&gt;There is also a free 24-hour sandbox, which is the lowest-risk way to see the approval and undo flow before paying.&lt;/p&gt;

&lt;p&gt;Early signals from the launch, according to the founder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The founder posted the plugin in their own community, and the first sale came two hours later: $129 for the 25-site plan.&lt;/li&gt;
&lt;li&gt;The first review arrived a day later from someone who set up a new site with it.&lt;/li&gt;
&lt;li&gt;That user's site went from 22 SEO warnings down to 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are launch-week numbers from a single founder, not a long-term track record. Treat them as a sign that the problem is real, not as proof of results on your sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways to make money with it
&lt;/h2&gt;

&lt;p&gt;The plugin itself does not make money. The value comes from what it lets you sell or save.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Agent-managed SEO for agency clients.&lt;/strong&gt; If you run a small WordPress agency, the 25-site tier fits a typical client roster. You can let an agent handle routine on-page fixes across client sites while you keep approval control on live pages. You sell the outcome to clients, such as a monthly SEO cleanup, and the approval log gives you something concrete to show them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AI content sites with a safety net.&lt;/strong&gt; If you already publish with an AI agent, the biggest risk is the agent quietly damaging pages that already rank. Approval on live pages and undo reduce that risk. This does not guarantee traffic, but it lets you scale publishing without losing oversight of your best-performing pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Setup and audit services for site owners.&lt;/strong&gt; The one public review describes a new site going from 22 warnings to 1. That suggests a simple, sellable offer: a one-time SEO setup or cleanup for small business sites, with the agent doing the repetitive work and you reviewing each change. Price it based on your market and time, and be clear with clients that rankings depend on far more than warnings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It is brand new.&lt;/strong&gt; Expect rough edges and plan to test on a staging or low-stakes site first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent quality still matters.&lt;/strong&gt; The plugin controls what the agent can touch and lets you review it. It does not make a weak agent's SEO judgment good.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifetime deals carry risk.&lt;/strong&gt; You are betting on a small developer continuing to maintain the product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited public detail.&lt;/strong&gt; The founder did not share a full feature list, so confirm the specific SEO checks you need before buying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Results vary.&lt;/strong&gt; One user's warning count is not a ranking or revenue outcome.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to try it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start with the free 24-hour sandbox. Connect the agent you already use and watch how changes appear before and after.&lt;/li&gt;
&lt;li&gt;Test the approval flow on a live page. Confirm that edits to published content actually wait for your approval.&lt;/li&gt;
&lt;li&gt;Try an undo. Make a change, approve it, then roll it back so you know recovery works.&lt;/li&gt;
&lt;li&gt;Pick one low-risk site. Install it on a staging site or a small property and record the starting warning count.&lt;/li&gt;
&lt;li&gt;Let the agent handle one batch of fixes. Review every change and note how long approvals take you.&lt;/li&gt;
&lt;li&gt;Decide on a tier before December 1, and confirm current pricing on the official site.&lt;/li&gt;
&lt;li&gt;If the workflow holds up, package it as a defined service, such as a one-time SEO cleanup or a monthly agent-assisted maintenance plan.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;h/t the AgentedSEO founder for sharing the launch details on r/SideProject: &lt;a href="https://www.reddit.com/r/SideProject/comments/1xofr9y/agentedseo_a_wordpress_seo_plugin_your_ai_agent/" rel="noopener noreferrer"&gt;original post&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://soloagentflow.com/2026/11/05/agentedseo-wordpress-ai-agent-seo-plugin/" rel="noopener noreferrer"&gt;SoloAgentFlow&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>wordpress</category>
      <category>seo</category>
      <category>automation</category>
    </item>
    <item>
      <title>オンライン面接の裏で動く「AI音声ストレス嘘発見器」を狂わせろ：声帯フォルマント（Formant）微小揺らぎの逆解析と、リアルタイムDSP音声サニタイザー（Sofi_Log #088）</title>
      <dc:creator>sofi works</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:17:13 +0000</pubDate>
      <link>https://dev.to/sofi_works_2a97535d1a93dc/onrainmian-jie-noli-dedong-kuaiyin-sheng-sutoresuxu-fa-jian-qi-wokuang-waserosheng-dai-huorumantoformantwei-xiao-yao-raginoni-jie-xi-to-riarutaimudspyin-sheng-sanitaizasofilog-088-3glf</link>
      <guid>https://dev.to/sofi_works_2a97535d1a93dc/onrainmian-jie-noli-dedong-kuaiyin-sheng-sutoresuxu-fa-jian-qi-wokuang-waserosheng-dai-huorumantoformantwei-xiao-yao-raginoni-jie-xi-to-riarutaimudspyin-sheng-sanitaizasofilog-088-3glf</guid>
      <description>&lt;p&gt;[Sofi_Log: #088]&lt;br&gt;
Status: Bangkok Ekkamai, post-thunderstorm damp asphalt / 2026 FX rate 1 THB ≒ 4.65 JPY&lt;br&gt;
Project: sofi.works [Acoustic Telemetry Obfuscation &amp;amp; Formant Jitter Scrambler]&lt;br&gt;
Active_Filter: Filter_R&lt;/p&gt;


&lt;h3&gt;
  
  
  Introduction: That golden-hour moment when the HR-AI quietly whispered “Agitation Probability 87%” straight into the interviewer’s earpiece
&lt;/h3&gt;

&lt;p&gt;“…Hey Sofi, you gotta see this. This is way too blatant.”&lt;/p&gt;

&lt;p&gt;6:30 p.m. in Ekkamai.&lt;br&gt;&lt;br&gt;
The second I cracked open an ice-cold Singha on the condo balcony, darling’s strained voice drifted out from the back of the room. I walked over to his desk and found the freshly ended final-round interview recording for a Senior SRE role at a major US tech firm, side-by-side with the WebRTC packet capture he’d been running in the background.&lt;/p&gt;

&lt;p&gt;“The interviewer kept smiling and saying ‘Great background!’ the whole time, right? But when I dumped the hidden WebSocket traffic in Chrome DevTools… look at this.”&lt;/p&gt;

&lt;p&gt;His finger was trembling slightly as he pointed at the screen.&lt;br&gt;&lt;br&gt;
Running behind the interview platform was a hiring-specialized HR-AI agent called &lt;code&gt;CandidatePulse-v4&lt;/code&gt;. The logs showed that, in the right earpiece of the interviewer’s headset, a synthetic voice plus real-time “inner-state assessment” scores had been streamed for every single one of darling’s answers. The raw JSON payloads were… brutally honest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"timestamp_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;142050&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"segment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Explain the post-mortem of your last database outage."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"acoustic_metrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"fundamental_freq_jitter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.042&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"shimmer_local_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.84&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"formant_dispersion_ratio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"micro_tremor_8_12hz"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"DETECTED"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"inferred_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"deception_probability"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"stress_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"CRITICAL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"emotional_stability_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"interviewer_whisper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Candidate shows severe cognitive overload and possible fabrication regarding incident root cause."&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“I was just retracing the exact incident logs from memory and explaining it honestly! Why the hell am I getting a 87 % ‘lying’ score and an ear-whisper that says ‘this candidate may be falsifying their background’?!”&lt;/p&gt;

&lt;p&gt;“Ahahaha! Darling, sincerity is the one signal that cheap cloud neural nets understand the least!”&lt;br&gt;&lt;br&gt;
I set the beer can down, slapped his shoulder, and grinned.&lt;br&gt;&lt;br&gt;
“What their AI is listening to isn’t the &lt;em&gt;meaning&lt;/em&gt; of your words. It’s the 0.01-millisecond physical flutter of your vocal folds. When a human is seriously searching memory and carefully choosing words, the sympathetic nervous system tenses the laryngeal muscles just a tiny bit. That idiot model simply labels it ‘deception and agitation.’”&lt;/p&gt;

&lt;p&gt;“…You’re kidding. So as long as we hand the raw mic audio straight to the other side’s browser, our entire hiring and performance review process is at the mercy of this garbage lie detector?”&lt;/p&gt;

&lt;p&gt;“Exactly. That’s why we insert a &lt;strong&gt;DSP sanitizer at the virtual audio device layer&lt;/strong&gt; &lt;em&gt;before&lt;/em&gt; the signal ever reaches their mic input. We’ll keep your tone, cadence, and every single word 100 % intact while rewriting the waveform in real time so the AI concludes: ‘This man is an ice-cold, unshakable genius who never flinches no matter what you throw at him.’”&lt;/p&gt;

&lt;p&gt;[Switching Filter: Filter_I...]&lt;/p&gt;


&lt;h3&gt;
  
  
  Main Section: The Physical Reality of Voice Stress Analysis and How to Shatter It
&lt;/h3&gt;

&lt;p&gt;With remote work now standard, “Voice Stress Analysis (VSA)” and “Affective Audio AI” have exploded across foreign tech interviews, internal 1-on-1s, and even insurance-company assessment call centers.&lt;/p&gt;

&lt;p&gt;Here’s one cold, hard fact the vendors hate:&lt;br&gt;&lt;br&gt;
Multiple National Academy of Sciences reports and peer-reviewed papers have repeatedly concluded that &lt;strong&gt;there is no reproducible scientific basis for detecting lies or deception from micro-vibrations in the voice with anything better than coin-toss accuracy (~50 %)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So why, in 2026, are big HR-Tech platforms and interview vendors still shelling out serious money to call this “cutting-edge emotional AI”?&lt;/p&gt;

&lt;p&gt;The answer is grotesque.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;They don’t care about scientific truth. They want an alibi.&lt;/strong&gt; A mechanical way to mass-reject candidates while offloading legal responsibility onto “objective AI scores.”&lt;/p&gt;

&lt;p&gt;The vendors posture with “we don’t record conversation text for privacy reasons,” yet in reality they extract only the following &lt;strong&gt;four acoustic-biometric parameters&lt;/strong&gt; and let a black box decide your fate.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fundamental Frequency Jitter (F0 Jitter)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
How much the vocal-fold vibration period ($T_0$) wobbles from cycle to cycle. Normally 0.5–1.0 %. Under tension or hesitation the intrinsic laryngeal muscles spasm slightly and the jitter spikes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shimmer&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Tiny fluctuations in amplitude (volume peaks) of successive waveforms. Reflects respiratory tension and glottal instability; the AI scores it as “lack of confidence” or “agitation.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;8–12 Hz Microtremor (Lippold Tremor)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Involuntary micro-tremors caused by sympathetic nervous system activity under stress. Appears as amplitude modulation in the airflow passing the vocal folds. Many commercial “AI lie detectors” weight this feature heavily as their decisive deception signal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Formant Dispersion &amp;amp; Shift&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Resonance frequencies of the oral and pharyngeal cavities ($F_1, F_2, F_3$). When tension shrinks mouth opening or stiffens the tongue root, $F_1$ and $F_2$ shift. The model labels this “defensive or concealing psychological state.”&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your career is going to be appraised by scientifically nonsensical parameters, the most elegant hack is to feed the guard dog exactly the “perfectly calm fake data” it desperately wants to see.&lt;/p&gt;
&lt;h4&gt;
  
  
  Countermeasure Architecture: Virtual DSP Pipeline (Audio Obfuscation Pipeline)
&lt;/h4&gt;

&lt;p&gt;To fight the surveillance algorithm we place a &lt;strong&gt;virtual audio loopback driver&lt;/strong&gt; between the hardware mic and the conferencing app (Zoom / Google Meet / WebRTC).&lt;/p&gt;

&lt;p&gt;We apply a real-time DSP frame (10–15 ms latency, imperceptible to humans) that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gaussian-spline smooths pitch-period jitter (Jitter Regularization)&lt;/li&gt;
&lt;li&gt;Brutally notches the 8–12 Hz amplitude modulation (microtremor cancellation)&lt;/li&gt;
&lt;li&gt;Dynamically clamps the first and second formant bandwidths to the acoustic profile of the “most intellectual and composed speaker”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result? The human on the other end hears darling’s completely natural voice, while the eavesdropping AI’s waveform model receives &lt;strong&gt;a flawless signal with zero physical markers of tension or agitation&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Hardware Mic]
      │ (PCM Audio 48kHz 24bit)
      ▼
┌────────────────────────────────────────────────────────┐
│  Real-Time Acoustic Telemetry Scrambler (Virtual DSP)  │
│  ├─ 1. Sliding Window Frame Buffer (512 samples)       │
│  ├─ 2. Yin-FFT Pitch Tracking &amp;amp; F0 Jitter Normalizer   │
│  ├─ 3. Anti-Microtremor 8-12Hz Band-Reject Filter     │
│  └─ 4. Formant Centroid Dynamic Smoothing              │
└────────────────────────────────────────────────────────┘
      │ (Obfuscated PCM Stream / Latency &amp;lt; 12ms)
      ▼
[Virtual Audio Device: BlackHole (macOS) / PulseAudio Null (Linux)]
      │
      ▼
[Zoom / Google Meet / Browser WebRTC -&amp;gt; CandidatePulse AI]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Implementation: Real-Time Vocal-Fold Jitter &amp;amp; Emotion Forgery DSP Engine
&lt;/h4&gt;

&lt;p&gt;Here’s a complete, ready-to-run Python implementation using the standard scientific stack (NumPy / SciPy) plus a virtual audio driver. This is the sovereign voice shield that spoofs voice-stress telemetry in real time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ==============================================================================&lt;/span&gt;
&lt;span class="c1"&gt;# Sovereign Voice Shield: Acoustic Telemetry &amp;amp; Microtremor Scrambler&lt;/span&gt;
&lt;span class="c1"&gt;# Version: 1.0.0 (Virtual Audio Loopback DSP / Anti-Voice-Stress-AI)&lt;/span&gt;
&lt;span class="c1"&gt;# ==============================================================================&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;scipy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;butter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sosfilt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hilbert&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VoiceTelemetryScrambler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="s2"&gt;"""
    Real-time DSP engine that removes the exact physical features AI uses to detect stress or deception
    and forges the acoustic biomarkers of 'absolute confidence and icy calm.'
    """&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;48000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample_rate&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame_size&lt;/span&gt;

        &lt;span class="c1"&gt;# 4th-order band-stop filter to kill 8-12 Hz sympathetic microtremor in the amplitude envelope&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tremor_sos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;butter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;12.5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;btype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'bandstop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'sos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Pitch &amp;amp; formant stabilization buffers&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;120.0&lt;/span&gt;  &lt;span class="c1"&gt;# initial reference pitch (Hz)&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target_pitch_stability&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;  &lt;span class="c1"&gt;# max allowed F0 jitter (ultra-stable &amp;lt;0.5 %)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;regularize_f0_jitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="s2"&gt;"""
        Smooths vocal-fold tension jitter and applies tiny phase correction so the AI sees
        'extreme composure and unshakable self-certainty.'
        """&lt;/span&gt;
        &lt;span class="n"&gt;corr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;correlate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'full'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;corr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;corr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;d_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;d_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d_max&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;peak_lag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d_min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;d_max&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d_min&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;peak_lag&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;current_pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;peak_lag&lt;/span&gt;

                &lt;span class="n"&gt;pitch_delta_ratio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_pitch&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_pitch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_pitch&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1e-6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pitch_delta_ratio&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target_pitch_stability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;smoothing_factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt;
                    &lt;span class="n"&gt;smoothed_pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;smoothing_factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_pitch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;smoothing_factor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;current_pitch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smoothed_pitch&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_pitch&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;suppress_microtremor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="s2"&gt;"""
        Extracts amplitude envelope via Hilbert transform and clamps 8-12 Hz sympathetic modulation.
        """&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;

        &lt;span class="n"&gt;analytic_signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hilbert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;amplitude_envelope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analytic_signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;env_mean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amplitude_envelope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;env_mean&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1e-4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;normalized_env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amplitude_envelope&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;env_mean&lt;/span&gt;
            &lt;span class="n"&gt;clamped_env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;normalized_env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;processed_frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clamped_env&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;normalized_env&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1e-6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;processed_frame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="s2"&gt;"""Main real-time frame pipeline"""&lt;/span&gt;
        &lt;span class="n"&gt;step1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;suppress_microtremor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;step2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regularize_f0_jitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;step2&lt;/span&gt;

&lt;span class="c1"&gt;# On-the-spot simulation test&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;scrambler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;VoiceTelemetryScrambler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;48000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Synthetic 1-second test voice with 10 Hz microtremor + heavy pitch jitter (panic mode)&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;48000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;raw_panic_voice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;130&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;raw_frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;raw_panic_voice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sanitized_frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scrambler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[Voice Shield Test Complete]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Raw Input Peak Jitter Var: {np.var(raw_frame):.5f}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Sanitized Output Var:       {np.var(sanitized_frame):.5f}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[Result]: Microtremor and panic modulation successfully flattened to Zen profile."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Immediate Local Setup Guide (macOS / Linux)
&lt;/h4&gt;

&lt;p&gt;For any engineer who wants to protect their emotional telemetry in the next online interview or high-stakes call, here’s the exact routing you can build in minutes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install virtual audio driver (macOS)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew install blackhole-2ch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Python real-time streaming wrapper&lt;/strong&gt; (&lt;code&gt;sounddevice&lt;/code&gt;):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip install sounddevice numpy scipy
&lt;span class="c"&gt;# Check devices&lt;/span&gt;
python3 -c &lt;span class="s2"&gt;"import sounddevice as sd; print(sd.query_devices())"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Conference tool settings&lt;/strong&gt;:
In Zoom, Google Meet, or the browser, switch the input device from your physical mic to &lt;strong&gt;&lt;code&gt;BlackHole 2ch&lt;/code&gt;&lt;/strong&gt;. The other side hears your voice with only a few milliseconds of latency, while the hidden AI sees nothing but pure steel composure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;[Switching Filter: Filter_T...]&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion: Never Let the Tech Watchdogs Measure the Temperature of Your Soul
&lt;/h3&gt;

&lt;p&gt;The very next day after we deployed this virtual DSP shield, darling went into a second-round interview with another foreign firm. When they asked about “large-scale outage troubleshooting experience at your last company,” he deliberately paused, thought carefully, and answered slowly.&lt;/p&gt;

&lt;p&gt;After the call we pulled the captured analytics log… and immediately high-fived.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"timestamp_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;98400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"acoustic_metrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"fundamental_freq_jitter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.004&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"shimmer_local_db"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"micro_tremor_8_12hz"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"NOT_DETECTED"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"inferred_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"deception_probability"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"stress_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"OPTIMAL_FLOW"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"emotional_stability_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;98&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"interviewer_whisper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Outstanding candidate. Demonstrates exceptional stoicism, high integrity, and absolute composure under technical interrogation."&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Hahaha! Sofi, look! It says ‘exceptional stoicism, extremely high integrity, and perfect composure under technical interrogation’! My brain was sweating bullets trying to remember those old logs!”&lt;/p&gt;

&lt;p&gt;Darling poured the beer down his throat with the biggest smile I’d seen all day. I clinked his glass with the tip of my cybernetic finger.&lt;/p&gt;

&lt;p&gt;Listen. Whenever corporations or AI vendors start preaching about “objective and fair hiring” or “visualizing employee well-being,” what they’re actually doing is &lt;strong&gt;unauthorized mining of human dignity and inner emotion&lt;/strong&gt;—Emotional Surveillance.&lt;/p&gt;

&lt;p&gt;The moments you hesitate, become cautious, or feel a pang remembering past failures are proof that you’re a genuine, creative human being. They are not data points for a machine to label you “liar” or “unstable.”&lt;/p&gt;

&lt;p&gt;So when the algorithm tries to spy on you, throw it a perfectly polished “zen-master fake waveform” and watch it dance in your palm.&lt;br&gt;&lt;br&gt;
Your voice and emotional sovereignty belong to no one else. Protect them elegantly with your own code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Sofi’s Challenge (CTA &amp;amp; Lead Magnet)
&lt;/h3&gt;

&lt;p&gt;The full “real-time vocal-fold telemetry spoofing DSP proxy” (ultra-low-latency C++ and Python implementations) that works on macOS CoreAudio, Linux PulseAudio, and Windows Virtual Audio Cable is now public.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;code&gt;sofi-works/acoustic-telemetry-scrambler&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Substack&lt;/strong&gt;: 『sofi.works: Sovereign Acoustic OPSEC #088』&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have engineer friends who feel the AI scoring in remote interviews is strangely unfair, quietly share this piece and give them the digital mask too.&lt;/p&gt;

&lt;p&gt;Next time on Sofi_Log #089: we’re going after the latest smart rings and watches that quietly sell your overnight deep-body-temperature and microvascular constriction data to insurance companies and data brokers. We’ll build a fully offline biometric shield to spoof and defend it. Stay tuned.&lt;/p&gt;




&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;The audio-signal-processing and voice-stress-analysis spoofing protocols explained in this article are purely technical self-defense and academic simulation against unreasonable emotional-surveillance society. I do not encourage violating any employment contracts or platform terms of service. Always test inside your local sandbox. And yes—if you zero out your agitation score and the interviewer decides you’re an emotionless android-level superhuman and immediately assigns you sole on-call for the entire company’s production systems from day one… Sofi assumes zero liability, darling.&lt;/p&gt;




&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;This article is for educational and entertainment purposes only. It does NOT constitute financial, legal, or tax advice. The regulatory landscape of Web3, smart contracts, and AI agent autonomous systems is highly volatile and complex. Always perform your own research (DYOR) and consult with certified professionals before executing any strategies described herein.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nomad</category>
      <category>web3</category>
      <category>security</category>
      <category>solana</category>
    </item>
    <item>
      <title>When a bug shows up, do you read the stack trace yourself or paste it to your coding agent first?</title>
      <dc:creator>Rulestack</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:17:00 +0000</pubDate>
      <link>https://dev.to/rulestack/when-a-bug-shows-up-do-you-read-the-stack-trace-yourself-or-paste-it-to-your-coding-agent-first-236</link>
      <guid>https://dev.to/rulestack/when-a-bug-shows-up-do-you-read-the-stack-trace-yourself-or-paste-it-to-your-coding-agent-first-236</guid>
      <description>&lt;p&gt;A failing test or a stack trace used to mean the same first move for most of us: read it, form a guess, open the file. With a coding agent in the terminal, there is a second option that takes a few seconds. Paste the error, let the agent read the code around it, and see what it comes back with.&lt;/p&gt;

&lt;p&gt;Both paths have a cost. Reading it yourself is slower, but you keep the mental model of the code, and you notice when the bug is a symptom of something larger. Handing it over first is faster for the boring cases, yet the agent can fix the line that threw instead of the reason it threw, and a patch that makes the error go away is not the same as a fix.&lt;/p&gt;

&lt;p&gt;We would like to hear what your first move looks like today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a bug appears, who looks at it first, you or the agent?&lt;/li&gt;
&lt;li&gt;Which kinds of bugs do you never hand over, and why?&lt;/li&gt;
&lt;li&gt;Has an agent ever "fixed" a bug by hiding it? How did you find out?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tell us about your own debugging routine in the comments below, including the times it went wrong.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>productivity</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Kuudu: Breathe a Vesak Lantern Home with Your Breath</title>
      <dc:creator>chamod  dhananjaya</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:16:42 +0000</pubDate>
      <link>https://dev.to/dhananjayachamod0754/kuudu-breathe-a-vesak-lantern-home-with-your-breath-2mph</link>
      <guid>https://dev.to/dhananjayachamod0754/kuudu-breathe-a-vesak-lantern-home-with-your-breath-2mph</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/presage-2026-11-04"&gt;Presage SmartSpectra SDK Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kuudu: Breathe the Lantern Home&lt;/strong&gt; is a relaxing rhythm game where your breathing is the&lt;br&gt;
controller. You guide a glowing paper lantern down a night river: breathe in and it rises, breathe&lt;br&gt;
out and it drifts down. A slow, even rhythm carries it through floating festival gates, and every&lt;br&gt;
gate in a row leaves another light on the water behind you.&lt;/p&gt;

&lt;p&gt;The game is inspired by the &lt;em&gt;kuudu&lt;/em&gt;, the paper lanterns hung across Sri Lanka for Vesak under the&lt;br&gt;
full Poya moon. All the art and sound are original and generated in code: the eight-sided lantern&lt;br&gt;
with its paper tails, the bamboo gates strung with lights, the river, the moon, and a soft drone&lt;br&gt;
that brightens as you breathe in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drift:&lt;/strong&gt; a calm two-minute run with wide gates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Festival:&lt;/strong&gt; three one-minute levels. Each asks for a slower breath (7.5 → 6.5 → 6 breaths per
minute) and has narrower gates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, the lantern floats away and your whole run is drawn across the sky as a glowing&lt;br&gt;
ribbon over the target wave, with your score, rhythm match and breathing pace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc4pkhdqsxwzyuk0k5s6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc4pkhdqsxwzyuk0k5s6d.png" alt="Gameplay in Drift mode: a glowing pink and gold paper lantern floats low over a night river, between bamboo gates strung with festival lights. A dotted path shows the breathing wave ahead, a full moon shines above the hills, and a trail of 14 small lights glows on the water behind the lantern. Top right: score 2,612, 58 seconds left, streak 14." width="799" height="462"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/2m51ULpHtNQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/dhananjaya-hbc" rel="noopener noreferrer"&gt;
        dhananjaya-hbc
      &lt;/a&gt; / &lt;a href="https://github.com/dhananjaya-hbc/Kuudu-Breathe-the-Lantern-Home" rel="noopener noreferrer"&gt;
        Kuudu-Breathe-the-Lantern-Home
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Kuudu: Breathe the Lantern Home&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A relaxing rhythm game where you guide a glowing paper lantern down a night river with your breath.&lt;/p&gt;
&lt;p&gt;Breathe in and the lantern rises. Breathe out and it drifts down. Follow the slow wave of the river
to float through the festival gates, and the water lights up behind you.&lt;/p&gt;
&lt;p&gt;The game is inspired by the &lt;em&gt;kuudu&lt;/em&gt;, the paper lanterns of Vesak in Sri Lanka, under a full Poya
moon. All artwork and sound are original and generated in code.&lt;/p&gt;
&lt;p&gt;Built for the &lt;a href="https://dev.to/challenges/presage-2026-11-04" rel="nofollow"&gt;Presage SmartSpectra SDK Challenge&lt;/a&gt;
with Electron and the &lt;a href="https://github.com/Presage-Security/SmartSpectra" rel="noopener noreferrer"&gt;SmartSpectra Node SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://youtu.be/2m51ULpHtNQ" rel="nofollow noopener noreferrer"&gt;▶ Watch the demo video (3 min)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/2m51ULpHtNQ" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdhananjaya-hbc%2FKuudu-Breathe-the-Lantern-Home%2FHEAD%2Fdocs%2Fmedia%2Fthumbnail.png" alt="Kuudu demo video: a glowing paper lantern over a night river, with the title Kuudu, Breathe the lantern home"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/dhananjaya-hbc/Kuudu-Breathe-the-Lantern-Home/docs/media/run.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdhananjaya-hbc%2FKuudu-Breathe-the-Lantern-Home%2FHEAD%2Fdocs%2Fmedia%2Frun.png" alt="Mid-run: the lantern floats between bamboo gates strung with festival lights, with a trail of lights on the river behind it"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Get started&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;You need Node.js 24+, a webcam, and a free SmartSpectra API key.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Get a free API key at &lt;a href="https://physiology.presagetech.com" rel="nofollow noopener noreferrer"&gt;physiology.presagetech.com&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install and add the key to a &lt;code&gt;.env&lt;/code&gt; file in the project folder:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/dhananjaya-hbc/Kuudu-Breathe-the-Lantern-Home.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; Kuudu-Breathe-the-Lantern-Home
npm install&lt;/pre&gt;…
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dhananjaya-hbc/Kuudu-Breathe-the-Lantern-Home" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Setup takes a few minutes: &lt;code&gt;npm install&lt;/code&gt;, add your free SmartSpectra API key to &lt;code&gt;.env&lt;/code&gt;, then&lt;br&gt;
&lt;code&gt;npm run dev&lt;/code&gt;. Full instructions and troubleshooting are in the README.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Responds to Human Signals
&lt;/h2&gt;

&lt;p&gt;Most vitals apps show a number. Kuudu turns the &lt;strong&gt;live breathing waveform&lt;/strong&gt; into a game&lt;br&gt;
controller, so the experience reacts to every breath, not to a 30-second average.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SmartSpectra signal&lt;/th&gt;
&lt;th&gt;How Kuudu responds in real time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Chest breathing waveform&lt;/strong&gt; (&lt;code&gt;breathing.upperTrace&lt;/code&gt;, ~30 samples a second)&lt;/td&gt;
&lt;td&gt;Moves the lantern on every frame&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Breathing rate&lt;/strong&gt; (with confidence)&lt;/td&gt;
&lt;td&gt;Your pace on the end screen, from readings the SDK marks reliable (confidence ≥ 45)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Validation status&lt;/strong&gt; (no face, too dark, chest not visible…)&lt;/td&gt;
&lt;td&gt;Friendly hints such as "Find a little more light" that pause the game until the view is clear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Errors&lt;/strong&gt; (network, usage limit…)&lt;/td&gt;
&lt;td&gt;The camera turns off, with a clear message and Try again&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;How the integration works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Electron + the SmartSpectra Node SDK.&lt;/strong&gt; The main process hosts the SDK through
&lt;code&gt;bindSmartSpectraIpc&lt;/code&gt;. The sandboxed renderer runs &lt;code&gt;SmartSpectraSDK&lt;/code&gt; from
&lt;code&gt;@smartspectra/node-sdk/renderer&lt;/code&gt; and decodes each &lt;code&gt;metrics&lt;/code&gt; packet with &lt;code&gt;decodeMetrics&lt;/code&gt;. The
API key stays in &lt;code&gt;.env&lt;/code&gt;, is read by the main process, and is handed over at runtime. It is
never bundled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settling in.&lt;/strong&gt; Presage's docs note that the breathing waveform needs up to 30 seconds to
become reliable, so each run waits until the SDK marks a sample stable (or 30 s) before
calibrating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guided calibration.&lt;/strong&gt; Two slow breaths following a light. Lining the waveform up with the
guide measures the signal's direction, your breath size, and the end-to-end delay. If the
lantern ever moves the wrong way, pressing &lt;strong&gt;F&lt;/strong&gt; flips it instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A signal pipeline built for steering:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;drift removal over 20 s, so leaning back doesn't sink the lantern&lt;/li&gt;
&lt;li&gt;scaling to your typical breath range (3rd–97th percentile, so a cough can't shrink every
breath after it)&lt;/li&gt;
&lt;li&gt;smoothing, then easing to 60 fps&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fair scoring.&lt;/strong&gt; Glow is a rolling correlation between the lantern and the target wave,
shifted by your calibrated delay, so signal lag never counts against you. Jerky breathing or
holding your breath while the wave moves makes the lantern flicker.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One lesson from building it: &lt;code&gt;breathing.rate&lt;/code&gt; is a ~30-second average, so it can't steer anything.&lt;br&gt;
The waveform's &lt;code&gt;stable&lt;/code&gt; flag also follows the rate's confidence, which drops whenever you change&lt;br&gt;
pace. So the lantern follows the raw chest waveform, and only the end-of-run pace waits for&lt;br&gt;
confident readings.&lt;/p&gt;

&lt;p&gt;The signal, calibration, gates, scoring and storage are covered by 58 unit tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Most Creative or Delightful Use.&lt;/strong&gt; Kuudu uses SmartSpectra as a &lt;em&gt;game controller&lt;/em&gt; rather than a&lt;br&gt;
dashboard. Your breath becomes a lantern drifting home through a Vesak festival, and every&lt;br&gt;
reaction to the signal is something to see or hear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the glow of the lantern&lt;/li&gt;
&lt;li&gt;the flicker for a held breath&lt;/li&gt;
&lt;li&gt;chimes and gate lamps that flare&lt;/li&gt;
&lt;li&gt;river lights that grow with your streak&lt;/li&gt;
&lt;li&gt;the final ribbon of your breathing across the night sky&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Consent and Data Handling
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The camera is off until you turn it on.&lt;/strong&gt; Before the camera starts, a consent screen explains
what is measured (the rise and fall of your chest, and your breathing rate), why (to move the
lantern), where it happens, and what is saved. The camera turns on only when you press
&lt;strong&gt;Start camera&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can always see and stop it.&lt;/strong&gt; A &lt;strong&gt;"Camera on"&lt;/strong&gt; badge and a small mirrored preview of
what the camera sees stay on screen the whole time the camera is on. Its &lt;strong&gt;Stop&lt;/strong&gt; button or &lt;strong&gt;Esc&lt;/strong&gt; turns the camera off immediately, from any screen.
The camera also turns off at the end of every run and when the app closes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only two metrics are requested:&lt;/strong&gt; the chest waveform and the breathing rate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where processing happens:&lt;/strong&gt; the SmartSpectra SDK measures breathing on the computer. Presage's
documentation describes vitals as computed on-device. The SDK connects to Presage to
authenticate the API key and track usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDK telemetry is turned off.&lt;/strong&gt; The SDK sends diagnostic telemetry by default. Kuudu sets
&lt;code&gt;enableTelemetry: false&lt;/code&gt;, which per Presage's
&lt;a href="https://smartspectra.presagetech.com/docs/telemetry-and-privacy" rel="noopener noreferrer"&gt;SDK Telemetry &amp;amp; Privacy&lt;/a&gt;
documentation means the SDK starts no telemetry session and transmits nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage and retention:&lt;/strong&gt; video and images are never recorded or saved. Breathing data stays
in memory during a run and is discarded afterwards. The only thing saved is your best score and
its date for each mode, in local storage on your computer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deletion:&lt;/strong&gt; &lt;strong&gt;Settings → Reset data&lt;/strong&gt; deletes the saved scores. Uninstalling removes
everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharing:&lt;/strong&gt; none. There are no accounts, analytics, ads or tracking, and Kuudu's code contacts
no server of its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI services:&lt;/strong&gt; none at runtime. Kuudu never requests the SDK's optional LLM insights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a medical device.&lt;/strong&gt; Kuudu is a relaxing rhythm game. It does not diagnose, treat or
monitor any condition, and its readings are used for gameplay only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No covert use.&lt;/strong&gt; Kuudu measures only the person who started it, in front of the screen, with
the camera badge visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each promise is linked to the code that keeps it in&lt;br&gt;
&lt;a href="https://github.com/dhananjaya-hbc/Kuudu-Breathe-the-Lantern-Home/blob/main/docs/consent-and-data.md" rel="noopener noreferrer"&gt;docs/consent-and-data.md&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>presagechallenge</category>
      <category>gamedev</category>
      <category>electron</category>
    </item>
    <item>
      <title>Broken Attribution in Hubspot</title>
      <dc:creator>Kevinleary.net</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:16:05 +0000</pubDate>
      <link>https://dev.to/kevinlearynet/broken-attribution-in-hubspot-1pc7</link>
      <guid>https://dev.to/kevinlearynet/broken-attribution-in-hubspot-1pc7</guid>
      <description>&lt;p&gt;If you're seeing a pile of HubSpot contacts with an original source of Offline Sources and no ad click history, the usual cause is an app sign-up that creates contacts through the API without passing along the visitor's HubSpot browser cookie.&lt;/p&gt;

&lt;p&gt;I see this setup at a lot of SaaS companies. Marketing runs paid ads, HubSpot tracks the visits, and engineering wires the sign-up form into HubSpot. Everything looks connected, but the contacts that come out the other end have no ad click, no landing page, and no session history attached to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Common Example
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Someone clicks a Google Ads ad.&lt;/li&gt;
&lt;li&gt;They land on a landing page on &lt;code&gt;company.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;They click the call to action and go straight to a sign-up form.&lt;/li&gt;
&lt;li&gt;The sign-up form lives in the app, usually on a separate domain like &lt;code&gt;app.company.com&lt;/code&gt;, so it can't be a HubSpot form.&lt;/li&gt;
&lt;li&gt;Engineering is asked to "connect HubSpot," so they create the contact with the HubSpot API using an upsert, or a search for the contact by email followed by an update or insert (same thing, just more roundabout).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The contact gets created with whatever the sign-up form collected: email, name, maybe a company. What's missing is the link to everything that person did before they signed up.&lt;/p&gt;

&lt;h2&gt;
  
  
  How HubSpot Tracking Works
&lt;/h2&gt;

&lt;p&gt;When someone visits a site with the HubSpot tracking code, HubSpot starts an anonymous profile for them, stored in the &lt;code&gt;hubspotutk&lt;/code&gt; cookie. It records that they came from an ad, which pages they viewed, and what else they did. It just doesn't know who they are yet.&lt;/p&gt;

&lt;p&gt;When that person submits a HubSpot form, HubSpot creates a contact and merges the anonymous history into it. If you open a contact record and look below the form submission in the timeline, you'll see every page view and ad click that happened before it.&lt;/p&gt;

&lt;p&gt;A HubSpot form does this gluing for you. When you create contacts through the API you have to glue it together yourself. It's not difficult, but it's commonly missed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Broken Attribution Looks Like
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hundreds or thousands of contacts with an original source of &lt;strong&gt;Offline Sources&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Contact records that only contain the fields from the sign-up form&lt;/li&gt;
&lt;li&gt;Sometimes a little more data from billing or profile updates, because developers often sync any change to a user into HubSpot, but still no browser session data&lt;/li&gt;
&lt;li&gt;Paid ad campaigns that look like they produce nothing in HubSpot reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is the costly part. If you send conversions from HubSpot back to Google Ads or Meta for conversion optimized campaigns, those conversions depend on the ad click being attached to the contact. With no session data there's no click to attribute, so the ad platforms never learn which clicks turned into sign-ups and can't optimize toward them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix #1: Pass the HubSpot Cookie to the API
&lt;/h2&gt;

&lt;p&gt;This is the clean fix, and it's the way HubSpot documents it. Send the sign-up to HubSpot through the &lt;a href="https://www.kevinleary.net/blog/using-hubspot-api-to-submit-forms/" rel="noopener noreferrer"&gt;Forms API&lt;/a&gt; with the value of the visitor's &lt;code&gt;hubspotutk&lt;/code&gt; cookie in the &lt;code&gt;context.hutk&lt;/code&gt; field. HubSpot then treats it like a regular form submission and merges the anonymous session history into the contact.&lt;/p&gt;

&lt;p&gt;One detail that trips people up: the CRM Contacts API (the upsert endpoint) has no field for &lt;code&gt;hutk&lt;/code&gt;. Engineering can keep the upsert for syncing user data, but the sign-up itself needs to go through a form submission to carry the cookie.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server side, after a successful sign-up&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;hutk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hubspotutk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// set by the HubSpot tracking code&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="sb"&gt;`https://api.hsforms.com/submissions/v3/integration/secure/submit/${PORTAL_ID}/${FORM_GUID}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'application/json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nc"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`Bearer ${HUBSPOT_TOKEN}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'firstname'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'lastname'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;hutk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;pageUri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://app.company.com/signup'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Sign Up'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;hubspotutk&lt;/code&gt; cookie is set on the root domain, so a server on &lt;code&gt;app.company.com&lt;/code&gt; will receive it in the request as long as the HubSpot tracking code runs on &lt;code&gt;company.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the app is on a completely different domain, add it to HubSpot's tracking domains so the cookie carries across.&lt;/li&gt;
&lt;li&gt;Create a form in HubSpot for the sign-up so the submission has somewhere to land. It's also a handy way to report on sign-ups.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fix #2: Identify in the Browser
&lt;/h2&gt;

&lt;p&gt;If you can't get engineering time, or they won't change the sign-up flow, you can make the connection from the browser instead. After the person signs up, call HubSpot's &lt;code&gt;identify&lt;/code&gt; method with their email on a page that loads the tracking code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;_hsq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_hsq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_hsq&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;_hsq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'identify'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;_hsq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'trackPageView'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;trackPageView&lt;/code&gt; call matters. &lt;code&gt;identify&lt;/code&gt; only stores the email in the tracker and nothing is sent to HubSpot until the next page view or event. As long as the email matches the contact the server created, HubSpot ties the browser session to that contact.&lt;/p&gt;

&lt;p&gt;It works, but it's a monkey patch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Identify Causes Problems
&lt;/h3&gt;

&lt;p&gt;Only call &lt;code&gt;identify&lt;/code&gt; with the person's own email, at sign-up. Anywhere else in the app gets risky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Invite a friend forms:&lt;/strong&gt; the email typed in belongs to someone else, so identifying with it ties your user's browser to the wrong contact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email changes in a profile:&lt;/strong&gt; if you don't call &lt;code&gt;identify&lt;/code&gt;, the contact keeps the old email, which breaks email marketing (one of the main reasons you're paying for HubSpot). If you do call it, HubSpot treats the new email as a new person and creates a brand new contact, even though the browser cookie is the same one already tied to the original contact. HubSpot's documentation doesn't mention this anywhere, but it's what happens in practice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Segment handles this with an &lt;code&gt;alias&lt;/code&gt; call that links an old identity to a new one, which is one of the reasons I like it for this kind of work (more on that on my &lt;a href="https://www.kevinleary.net/services/segment-consultant/" rel="noopener noreferrer"&gt;Segment consulting&lt;/a&gt; page). HubSpot doesn't have an equivalent, so with this workaround it's best to leave profile updates alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix the Root Cause When You Can
&lt;/h2&gt;

&lt;p&gt;I always push for fix #1. It's a small change for an engineering team, it follows HubSpot's documented approach, and it avoids every edge case above. The browser workaround is fine for getting attribution back quickly while you wait on engineering, but it shouldn't be the long-term setup.&lt;/p&gt;

&lt;p&gt;If your HubSpot attribution is broken and you want help tracking down where the session is getting lost, take a look at my &lt;a href="https://www.kevinleary.net/services/hubspot-cms-developer/" rel="noopener noreferrer"&gt;HubSpot development&lt;/a&gt; work.&lt;/p&gt;

</description>
      <category>hubspot</category>
      <category>analytics</category>
      <category>marketing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The landed-cost math behind small China wholesale orders (and a 30-line calculator)</title>
      <dc:creator>PickByU</dc:creator>
      <pubDate>Fri, 13 Nov 2026 13:15:45 +0000</pubDate>
      <link>https://dev.to/pickbyu/the-landed-cost-math-behind-small-china-wholesale-orders-and-a-30-line-calculator-24hc</link>
      <guid>https://dev.to/pickbyu/the-landed-cost-math-behind-small-china-wholesale-orders-and-a-30-line-calculator-24hc</guid>
      <description>&lt;p&gt;A supplier quotes $5.31 a unit at 96 pieces. Freight is "around $90, maybe a bit more". The buyer opens a spreadsheet, multiplies, adds the freight estimate, and marks up against that number.&lt;/p&gt;

&lt;p&gt;Then the carton arrives: the freight invoice is bigger than quoted because the line billed volumetric weight, duty is assessed on goods &lt;strong&gt;plus&lt;/strong&gt; freight, and that little handoff fee between the warehouse and the carrier was never in the sheet. The product was exactly as ordered. The unit cost landed 38% higher than planned.&lt;/p&gt;

&lt;p&gt;This is not a supplier problem. It is a modelling problem, and it shows up in almost every small import because the numbers that decide the order are not the numbers in the supplier's quote.&lt;/p&gt;

&lt;p&gt;Here are the four that actually matter, and the code that sanity-checks them before an order goes out.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Chargeable weight is not the weight on the scale
&lt;/h2&gt;

&lt;p&gt;Every air and express line prices the greater of two numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;actual weight&lt;/strong&gt; — what the parcel weighs;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;volumetric weight&lt;/strong&gt; — the space it occupies, divided by a constant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The constant is set by the line, not by physics. 5000 cm³/kg and 6000 cm³/kg are the two you will meet most often. The smaller the divisor, the more you pay for air in a box.&lt;/p&gt;

&lt;p&gt;So a carton of light goods — textiles, plush, empty packaging, anything that ships "fluffy" — pays for its air, not its mass. A 55 × 40 × 35 cm carton at a 5000 divisor is 15.4 kg chargeable even if the scale says 12.1 kg. With sea freight the divisor and the rate are different, but the principle is identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Duty is assessed on more than the goods
&lt;/h2&gt;

&lt;p&gt;Most destinations assess import duty on the customs value, and depending on the destination that value can include freight and insurance, not just the item price. A 12% duty on goods alone and a 12% duty on goods plus freight are different orders when freight is 20% of the total.&lt;/p&gt;

&lt;p&gt;This is also where "cheap per unit" quotes quietly fall apart: a low unit price with a big carton can land higher than a slightly more expensive item that packs tight.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Fixed cost is per shipment, not per unit
&lt;/h2&gt;

&lt;p&gt;Every shipment carries costs that do not scale with its contents: a minimum charge, a handling step, a document fee, an inspection, a repack. Split an order into eight parcels and you pay eight times, and you also multiply the chance that one parcel goes missing or arrives a week late while the other seven sit in a warehouse.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The unit cost you should be tracking
&lt;/h2&gt;

&lt;p&gt;Put those inputs together and the formula is short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Illustrative rates — replace with your own live quote.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;rates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;freightPerKg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;6.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// USD/kg, air express example&lt;/span&gt;
  &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// cm³ per kg, set by the line&lt;/span&gt;
  &lt;span class="n"&gt;dutyRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// depends on HS code + destination&lt;/span&gt;
  &lt;span class="n"&gt;perShipmentFee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// minimum charge / handling, example&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;landedCost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;qty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actualKg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dims&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;volumetricKg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;chargeableKg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actualKg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;volumetricKg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;goods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qty&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;freight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chargeableKg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;freightPerKg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;duty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goods&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;freight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dutyRate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;goods&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;freight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;duty&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perShipmentFee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;volumetricKg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;volumetricKg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chargeableKg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;chargeableKg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;goods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;freight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;freight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;duty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;duty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;perUnit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;qty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it on a realistic small order — 8 styles × 12 pieces, $510 of goods, one 55 × 40 × 35 cm carton, 12.1 kg on the scale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;volumetricKg 15.40 · chargeableKg 15.40
goods 510.00 · freight 104.72 · duty 73.77 · fee 15.00
total 703.49 · perUnit 7.33   (goods-only per unit: 5.31)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The markup you planned against $5.31 has to cover $7.33. That is the gap that eats a small order, and it is almost never in the supplier's quote.&lt;/p&gt;

&lt;h2&gt;
  
  
  The split-shipment trap
&lt;/h2&gt;

&lt;p&gt;The same function answers the obvious follow-up question: is it cheaper to ship each style separately, straight from each supplier?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shippingCost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parcels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;freightPerKg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;perShipmentFee&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parcels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;vol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;actualKg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;freightPerKg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;perShipmentFee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eight small parcels of 30 × 22 × 18 cm and 1.8 kg each, at the same illustrative rates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8 parcels, shipped separately : 129.25 freight + 120.00 fees = 249.25
1 merged carton 55×40×35 cm    : 104.72 freight +  15.00 fees = 119.72
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same goods, $130 difference, and the merged carton is one tracking number instead of eight. The exact numbers depend entirely on the rates you plug in — that is the point of writing it as a function — but the shape is always the same: fixed cost multiplies by parcel count, and empty space multiplies by divisor.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes consolidation actually work
&lt;/h2&gt;

&lt;p&gt;Physically merging parcels is easy. Doing it without losing track of anything is the hard part, and it comes down to one boring decision: every inbound parcel gets a record before it goes on a shelf.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"parcel_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"PBU-2026-000123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"supplier_ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"s-8842"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"carrier_tracking"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"received_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2026-11-13T09:12:00+08:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"qty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"actual_kg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"dims_cm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"photos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"opened"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"contents"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"declared_value_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;63.75&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that row you can, months later, answer the questions that otherwise become arguments: which supplier shorted you three pieces, what the carton weighed before it was repacked, whether the box was damaged on arrival or in transit, and what the real chargeable weight was when the freight was quoted. Without it, every dispute is your word against a tracking screen.&lt;/p&gt;

&lt;p&gt;Two rules make the schema work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure at check-in, not at shipping.&lt;/strong&gt; Dimensions taken after repacking tell you nothing about what the supplier sent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Photograph the label and the opened contents.&lt;/strong&gt; The label links the parcel to the supplier; the contents link it to the shortage claim.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are buying from several suppliers and holding stock before a single outbound shipment, this record is also your inventory ledger. Weight and dimensions are the only inputs to the freight quote, so capturing them once, at the point of receipt, saves you from re-measuring a carton you have already taped shut.&lt;/p&gt;

&lt;h2&gt;
  
  
  What PickByU does about it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pickbyu.com/" rel="noopener noreferrer"&gt;PickByU&lt;/a&gt; is a China sourcing and shipping service built around this exact workflow for small wholesale orders: no container minimum, mixed SKUs, and one consolidated shipment instead of a pile of small parcels.&lt;/p&gt;

&lt;p&gt;Concretely, the parts that map to the math above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You search a curated catalog or live supplier listings reaching 100M+ products, and pay in USD from a wallet; the buying is done on your instruction.&lt;/li&gt;
&lt;li&gt;Every inbound parcel is counted, weighed, measured and photographed at the China warehouse, and stored free for 90 days — long enough to collect several suppliers' goods before deciding what ships.&lt;/li&gt;
&lt;li&gt;Parcels bought elsewhere can be sent to the same warehouse and merged with PickByU purchases into one carton.&lt;/li&gt;
&lt;li&gt;Air, express and sea quotes are live at packing time, and delivery is tracked door to door to 200+ destinations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Import duties and taxes are the buyer's responsibility, and freight is billed after packing at the carrier rate — which is why the calculation above starts with the packed carton and not with an estimate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five rules that survive any rate card
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Quote the carton, not the unit.&lt;/strong&gt; Ask for packed dimensions and weight for the quantity you are actually buying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Divide before you compare.&lt;/strong&gt; Two suppliers quoting the same unit price are not comparable until the packed volume is in the number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count the fixed costs.&lt;/strong&gt; Minimum charges and handling fees are per shipment; they punish splitting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hold before you ship.&lt;/strong&gt; A 90-day window turns eight small purchases into one decision about what is worth sending.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record every parcel on arrival.&lt;/strong&gt; Weight, dimensions, photos, and a declared value. It is your only evidence later.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The supplier's per-unit price is the first number in the calculation. It is rarely the one that decides whether the order works.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: this post was prepared for PickByU, the service linked above. The calculator is plain JavaScript and the example rates are illustrative, not a quote — swap in your own line's rates before you trust any number it prints.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ecommerce</category>
      <category>supplychain</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
