<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Parallelisation on Ocarina — manual</title>
    <link>https://mojo-molotov.github.io/from-ocarina-to-igor/tags/parallelisation/</link>
    <description>Recent content in Parallelisation on Ocarina — manual</description>
    <generator>Hugo</generator>
    <language>en-US</language>
    <lastBuildDate>Sat, 30 May 2026 15:59:37 +0200</lastBuildDate>
    <atom:link href="https://mojo-molotov.github.io/from-ocarina-to-igor/tags/parallelisation/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>08.04 — Test strategy</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/08-ai-example/04-test-strategy/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/08-ai-example/04-test-strategy/</guid>
      <description>&lt;h1 id=&#34;0804test-strategy&#34;&gt;08.04 — Test strategy&lt;a class=&#34;anchor&#34; href=&#34;#0804test-strategy&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Six &lt;strong&gt;test types&lt;/strong&gt;, six distinct roles. Documented in &lt;code&gt;CURA_TEST_STRATEGY.md&lt;/code&gt; §3.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;test-types&#34;&gt;Test types&lt;a class=&#34;anchor&#34; href=&#34;#test-types&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Type&lt;/th&gt;&#xA;          &lt;th&gt;Expected status&lt;/th&gt;&#xA;          &lt;th&gt;Authoritative source&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Happy path&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;PASS&lt;/td&gt;&#xA;          &lt;td&gt;Nominal flows described from the FRDs&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Unhappy path&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;PASS (the test passes when the app correctly refuses)&lt;/td&gt;&#xA;          &lt;td&gt;Existing validations work&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Edge case / boundary&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;PASS or FAIL&lt;/td&gt;&#xA;          &lt;td&gt;Depending on the test, often accompanied by a note added to the FRDs&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Business logic vulnerability / gap test&lt;/strong&gt; (functional tests trying to &amp;ldquo;break&amp;rdquo; the product and identify gaps)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Intentional FAIL&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Behaviors a system should prevent but CURA doesn&amp;rsquo;t&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Exploratory / observed-behaviour&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;PASS&lt;/td&gt;&#xA;          &lt;td&gt;Documents current behavior when the spec doesn&amp;rsquo;t cover it&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Permanent security regression fixture&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;PASS (= security holds)&lt;/td&gt;&#xA;          &lt;td&gt;Verifies a security fix holds (fixes that stay permanently in the test heritage)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;happy-path&#34;&gt;Happy path&lt;a class=&#34;anchor&#34; href=&#34;#happy-path&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Exercises the nominal flow with valid inputs and an authenticated user. Verifies that the system produces the correct output (confirmation, history entry, etc.).&lt;/p&gt;</description>
    </item>
    <item>
      <title>06.07 — OTP coordination flow &#43; deliberate imprecision</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/06-tests-workers/07-otp-coordination-flow/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/06-tests-workers/07-otp-coordination-flow/</guid>
      <description>&lt;h1 id=&#34;0607otp-coordination-flow--deliberate-imprecision&#34;&gt;06.07 — OTP coordination flow + deliberate imprecision&lt;a class=&#34;anchor&#34; href=&#34;#0607otp-coordination-flow--deliberate-imprecision&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;The backend&amp;rsquo;s reason to exist: let N parallel Ocarina workers &lt;strong&gt;retrieve the right OTP&lt;/strong&gt; for their &lt;em&gt;user&lt;/em&gt;, even when several OTPs are generated.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;flow&#34;&gt;Flow&lt;a class=&#34;anchor&#34; href=&#34;#flow&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │               Worker (among --workers 3 of Ocarina)               │&#xA;   └───────────────────────────────────────────────────────────────────┘&#xA;                                     │&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ Selenium opens the Dashboard login page                           │&#xA;   └─────────────────────────────────┬─────────────────────────────────┘&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ Acquire the distributed Redis lock (OTP_SEND_LOCK_KEY)            │&#xA;   │   → only this worker can click &amp;#34;Send OTP&amp;#34; during ACQ              │&#xA;   └─────────────────────────────────┬─────────────────────────────────┘&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ min_utc_date = datetime.now(UTC)                                  │&#xA;   └─────────────────────────────────┬─────────────────────────────────┘&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ L1 cache: record min_utc_date + username in the cache             │&#xA;   │   (keys reserved by reserve_free_cache_key)                       │&#xA;   └─────────────────────────────────┬─────────────────────────────────┘&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ Selenium types username + password + ticks OTP + click &amp;#34;REQ OTP&amp;#34;  │&#xA;   └─────────────────────────────────┬─────────────────────────────────┘&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ IGORISTAN UI: fetch /api/otp?_user=&amp;lt;username&amp;gt;                     │&#xA;   │   (x-api-key typed by Selenium into the UI)                       │&#xA;   └─────────────────────────────────┬─────────────────────────────────┘&#xA;                                     ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ TESTS-WORKERS /api/otp:                                           │&#xA;   │   generate(secret) → otpCode                                      │&#xA;   │   createdAt = floor(now/1000)*1000  ← ms stripped                 │&#xA;   │   event = { _user, otpCode, createdAt, expiresAt, ... }           │&#xA;   │   redis.set(&amp;#34;otp:&amp;lt;now&amp;gt;:&amp;lt;uuid&amp;gt;&amp;#34;, JSON, EX 360)                     │&#xA;   │   return event                                                    │&#xA;   └──────────────────────────────────┬────────────────────────────────┘&#xA;                                      ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ IGORISTAN UI: displays OTP screen                                 │&#xA;   └──────────────────────────────────┬────────────────────────────────┘&#xA;                                      ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ Release the OTP_SEND_LOCK_KEY Redis lock                          │&#xA;   └──────────────────────────────────┬────────────────────────────────┘&#xA;                                      ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ Selenium: retrieve_dashboard_otp_code(min_utc_date, _user)        │&#xA;   │   ↓                                                               │&#xA;   │   GET /api/otp-history  (x-api-key = IGOR_API_KEY)                │&#xA;   │   ↓                                                               │&#xA;   │   TESTS-WORKERS: SCAN otp:* + MGET → all events                   │&#xA;   │   ↓                                                               │&#xA;   │   client-side filter by _user                                     │&#xA;   │   filter createdAt &amp;gt;= min_utc_date - 1s                           │&#xA;   │   sort ASC by createdAt                                           │&#xA;   │   return first.otpCode                                            │&#xA;   └──────────────────────────────────┬────────────────────────────────┘&#xA;                                      ▼&#xA;   ┌───────────────────────────────────────────────────────────────────┐&#xA;   │ Selenium types the OTP into the Igoristan UI                      │&#xA;   │   → AUTHENTICATED_WITH_MFA                                        │&#xA;   └───────────────────────────────────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;race-conditions&#34;&gt;Race conditions&lt;a class=&#34;anchor&#34; href=&#34;#race-conditions&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Worker A: &lt;code&gt;min_utc_date_A = 13:27:53.123&lt;/code&gt;, generates OTP_A at 13:27:53.250.&lt;/li&gt;&#xA;&lt;li&gt;Worker B: &lt;code&gt;min_utc_date_B = 13:27:53.130&lt;/code&gt;, generates OTP_B at 13:27:53.470.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Without coordination, A could pick up OTP_B instead of OTP_A — the timestamps are close and truncated to the second.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
