<?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: Sandro</title>
    <description>The latest articles on DEV Community by Sandro (@xil).</description>
    <link>https://dev.to/xil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1162961%2F396c1c7a-e5f6-44a5-873b-ee0685d38e2b.png</url>
      <title>DEV Community: Sandro</title>
      <link>https://dev.to/xil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xil"/>
    <language>en</language>
    <item>
      <title>How Bug Hunter Evolved From a Test Runner Into a Self-Hosted Quality Intelligence Platform</title>
      <dc:creator>Sandro</dc:creator>
      <pubDate>Sun, 13 Sep 2026 17:05:15 +0000</pubDate>
      <link>https://dev.to/xil/how-bug-hunter-evolved-from-a-test-runner-into-a-self-hosted-quality-intelligence-platform-4096</link>
      <guid>https://dev.to/xil/how-bug-hunter-evolved-from-a-test-runner-into-a-self-hosted-quality-intelligence-platform-4096</guid>
      <description>&lt;p&gt;A few months ago, I wrote about Bug Hunter as a self-hosted testing tool for web applications and APIs.&lt;/p&gt;

&lt;p&gt;At that point, the project could already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;discover application routes,&lt;/li&gt;
&lt;li&gt;execute Playwright browser tests,&lt;/li&gt;
&lt;li&gt;run direct API scenarios,&lt;/li&gt;
&lt;li&gt;import OpenAPI definitions,&lt;/li&gt;
&lt;li&gt;collect runtime evidence,&lt;/li&gt;
&lt;li&gt;detect deterministic findings,&lt;/li&gt;
&lt;li&gt;reproduce supported failures,&lt;/li&gt;
&lt;li&gt;and generate reports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since then, the project has changed significantly.&lt;/p&gt;

&lt;p&gt;The biggest change is not one individual feature.&lt;/p&gt;

&lt;p&gt;It is the direction of the product itself.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter is no longer something I think of as just a test runner.&lt;/p&gt;

&lt;p&gt;It is becoming a self-hosted &lt;strong&gt;Quality Intelligence platform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The current goal is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Discover application behavior, generate and execute tests, detect regressions, explain failures, reduce test maintenance, and track product quality over time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And importantly, the core workflow still works without an LLM.&lt;/p&gt;

&lt;p&gt;AI is optional assistance, not the execution engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  The workflow is now much broader
&lt;/h2&gt;

&lt;p&gt;The current operator flow looks more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analyze application
→ build Application Map
→ create deterministic Test Plan
→ optionally generate AI suggestions
→ run tests
→ collect evidence
→ detect Quality Issues
→ qualify results
→ compare regressions
→ track reliability, coverage and performance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a very different product from the early version I shared.&lt;/p&gt;

&lt;p&gt;The focus has moved from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Run a scenario and detect a failure"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;toward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What changed in product quality, why did it change, and what should the operator investigate next?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Reliability became a first-class concept
&lt;/h2&gt;

&lt;p&gt;One of the first major improvements was reliability tracking.&lt;/p&gt;

&lt;p&gt;A failed test is not automatically treated as a confirmed product bug.&lt;/p&gt;

&lt;p&gt;The conceptual flow now looks more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;detected signal
→ Needs review
→ expected
   ignored
   observation
   quality_issue
→ regression evaluation where applicable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction matters.&lt;/p&gt;

&lt;p&gt;If a test produces seven signals, that does not automatically mean the product has seven bugs.&lt;/p&gt;

&lt;p&gt;Some signals may be browser noise.&lt;/p&gt;

&lt;p&gt;Some may be known behavior.&lt;/p&gt;

&lt;p&gt;Some may be expected.&lt;/p&gt;

&lt;p&gt;Some may become a confirmed &lt;code&gt;quality_issue&lt;/code&gt; only after review.&lt;/p&gt;

&lt;p&gt;That model makes the platform much more useful for real engineering workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Self-healing and likely-cause analysis
&lt;/h2&gt;

&lt;p&gt;Test maintenance is another problem I wanted to address.&lt;/p&gt;

&lt;p&gt;UI automation can become expensive when selectors or page structures change frequently.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter now includes a self-healing layer that can help identify alternative targets when an existing interaction no longer matches the application.&lt;/p&gt;

&lt;p&gt;The important rule is that healing is not silent magic.&lt;/p&gt;

&lt;p&gt;The system preserves evidence and keeps the behavior explainable.&lt;/p&gt;

&lt;p&gt;The same principle applies to failure analysis.&lt;/p&gt;

&lt;p&gt;Instead of simply showing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the platform can correlate evidence and surface a likely cause when there is enough information to support it.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser action
→ network request
→ HTTP 500
→ UI failed to update
→ likely cause: backend request failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I deliberately avoid labeling every console or network event as a root cause.&lt;/p&gt;

&lt;p&gt;Evidence and interpretation remain separate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Visual regression testing
&lt;/h2&gt;

&lt;p&gt;Visual testing is now part of the platform as well.&lt;/p&gt;

&lt;p&gt;The system can work with baseline screenshots and compare them with current execution results.&lt;/p&gt;

&lt;p&gt;The workflow includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;baseline
→ current screenshot
→ visual comparison
→ threshold evaluation
→ regression result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for catching changes that functional assertions may miss.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout shifts,&lt;/li&gt;
&lt;li&gt;missing elements,&lt;/li&gt;
&lt;li&gt;unexpected responsive changes,&lt;/li&gt;
&lt;li&gt;visual regressions after frontend changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to replace visual review.&lt;/p&gt;

&lt;p&gt;The goal is to make visual changes measurable and reproducible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Accessibility testing
&lt;/h2&gt;

&lt;p&gt;Accessibility testing was added as another quality signal.&lt;/p&gt;

&lt;p&gt;The platform can detect WCAG-related issues and associate them with the same project/run context as functional, visual and API testing.&lt;/p&gt;

&lt;p&gt;This is important to me because I do not want Universal Bug Hunter to become a collection of disconnected testing tools.&lt;/p&gt;

&lt;p&gt;Accessibility findings should live in the same quality model as other product evidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Knowledge
&lt;/h2&gt;

&lt;p&gt;Another large change was adding Project Knowledge.&lt;/p&gt;

&lt;p&gt;Applications often cannot be understood only from routes and DOM elements.&lt;/p&gt;

&lt;p&gt;Business requirements matter.&lt;/p&gt;

&lt;p&gt;Product documentation matters.&lt;/p&gt;

&lt;p&gt;Rules matter.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter can now ingest project documentation and retrieve relevant context for AI-assisted exploration.&lt;/p&gt;

&lt;p&gt;But there is an important security boundary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Project documentation is context, not permission.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A document cannot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expand allowed routes,&lt;/li&gt;
&lt;li&gt;enable destructive actions,&lt;/li&gt;
&lt;li&gt;override safety policy,&lt;/li&gt;
&lt;li&gt;introduce credentials,&lt;/li&gt;
&lt;li&gt;or bypass human approval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system treats retrieved project knowledge as untrusted reference material.&lt;/p&gt;

&lt;p&gt;That distinction is especially important when AI is involved.&lt;/p&gt;




&lt;h2&gt;
  
  
  API Intelligence moved beyond basic smoke tests
&lt;/h2&gt;

&lt;p&gt;The earlier version supported simple API smoke scenarios.&lt;/p&gt;

&lt;p&gt;That area has expanded significantly.&lt;/p&gt;

&lt;p&gt;The platform now has a stronger API testing model around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAPI contracts,&lt;/li&gt;
&lt;li&gt;request and response validation,&lt;/li&gt;
&lt;li&gt;parameters,&lt;/li&gt;
&lt;li&gt;authentication profiles,&lt;/li&gt;
&lt;li&gt;extracted variables,&lt;/li&gt;
&lt;li&gt;request chaining,&lt;/li&gt;
&lt;li&gt;assertions,&lt;/li&gt;
&lt;li&gt;negative cases,&lt;/li&gt;
&lt;li&gt;and boundary testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The intention is to keep browser and API testing connected to the same product quality model rather than building a separate API-testing product inside the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Impact Analysis and CI/CD integration
&lt;/h2&gt;

&lt;p&gt;Running every test for every code change does not always make sense.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter now supports Test Impact Analysis.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Git change
→ changed files
→ affected application areas
→ affected tests
→ recommended test set
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A critical design rule here is uncertainty handling.&lt;/p&gt;

&lt;p&gt;If the platform cannot confidently determine which tests are affected, it must not silently select zero tests.&lt;/p&gt;

&lt;p&gt;Instead, it falls back to a defined policy such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smoke
critical
all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;smoke&lt;/code&gt; is the default fallback, but the policy can also be configured to use &lt;code&gt;critical&lt;/code&gt; or &lt;code&gt;all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important rule is that uncertainty must not silently produce an empty test set.&lt;/p&gt;

&lt;p&gt;This makes the system usable in CI without creating false confidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quality Intelligence Dashboard
&lt;/h2&gt;

&lt;p&gt;The project now tracks quality across runs instead of looking only at one execution.&lt;/p&gt;

&lt;p&gt;The Quality area includes concepts such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Quality Issues
Regressions
Reliability
Coverage
Performance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dashboard intentionally avoids vanity metrics.&lt;/p&gt;

&lt;p&gt;If the system cannot calculate a trustworthy percentage, I prefer showing counts instead of inventing a percentage.&lt;/p&gt;

&lt;p&gt;Similarly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Regression not evaluated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is represented as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;—
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those details sound small, but they matter when people start making engineering decisions from dashboards.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance Intelligence
&lt;/h2&gt;

&lt;p&gt;Performance testing has also been integrated into the same workflow.&lt;/p&gt;

&lt;p&gt;The platform can execute performance measurements and compare them against approved baselines.&lt;/p&gt;

&lt;p&gt;The important part is that performance semantics remain separate from functional execution.&lt;/p&gt;

&lt;p&gt;A run can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;functionally successful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while performance regression status is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;not evaluated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are not the same outcome.&lt;/p&gt;

&lt;p&gt;The platform keeps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;execution status
performance verdict
release gate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as separate concepts.&lt;/p&gt;

&lt;p&gt;Another safety rule is that performance measurement does not re-run destructive browser workflows.&lt;/p&gt;

&lt;p&gt;Repeated API measurements are constrained to safe, read-only request patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  The enterprise layer
&lt;/h2&gt;

&lt;p&gt;One of the largest recent changes was Phase 35: the team and enterprise platform.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter now has an organization-based tenant model.&lt;/p&gt;

&lt;p&gt;The structure is roughly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
→ Organization Membership
→ Team / Project Grants
→ Capability-based permissions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A user can belong to multiple organizations.&lt;/p&gt;

&lt;p&gt;Teams belong to one organization.&lt;/p&gt;

&lt;p&gt;A normal member does not automatically receive access to every project.&lt;/p&gt;

&lt;p&gt;Authorization is evaluated through a central access-control service.&lt;/p&gt;

&lt;p&gt;I intentionally avoided spreading checks such as:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;through route handlers.&lt;/p&gt;

&lt;p&gt;Roles are labels over capabilities.&lt;/p&gt;

&lt;p&gt;The permission engine remains the authority.&lt;/p&gt;




&lt;h2&gt;
  
  
  Persistent collaborative triage
&lt;/h2&gt;

&lt;p&gt;Quality triage is now shared and persistent.&lt;/p&gt;

&lt;p&gt;When one authorized team member classifies a detected signal, that decision is stored as platform state.&lt;/p&gt;

&lt;p&gt;The supported classifications are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expected
ignored
observation
quality_issue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The decision includes revision tracking so concurrent edits can produce a conflict instead of silently overwriting another user's work.&lt;/p&gt;

&lt;p&gt;Confirmed &lt;code&gt;quality_issue&lt;/code&gt; classifications can then appear in the Quality Issues view without changing the original run result.&lt;/p&gt;

&lt;p&gt;That separation is intentional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Platform audit log
&lt;/h2&gt;

&lt;p&gt;Enterprise operations also need accountability.&lt;/p&gt;

&lt;p&gt;The platform now has an append-only application-level audit log for governance events such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;membership changes,&lt;/li&gt;
&lt;li&gt;teams,&lt;/li&gt;
&lt;li&gt;project grants,&lt;/li&gt;
&lt;li&gt;invitations,&lt;/li&gt;
&lt;li&gt;triage,&lt;/li&gt;
&lt;li&gt;service accounts,&lt;/li&gt;
&lt;li&gt;API tokens,&lt;/li&gt;
&lt;li&gt;OIDC configuration,&lt;/li&gt;
&lt;li&gt;and other administrative operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The audit log is tenant-scoped and redacted.&lt;/p&gt;

&lt;p&gt;I also try to be precise about what it is not.&lt;/p&gt;

&lt;p&gt;It is not currently a cryptographically immutable WORM audit system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Service accounts and API tokens
&lt;/h2&gt;

&lt;p&gt;CI/CD workflows should not depend on human accounts.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter now supports service accounts with scoped Bearer tokens.&lt;/p&gt;

&lt;p&gt;The security model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service-account permissions
∩
token scopes
=
effective token authority
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A token can reduce authority.&lt;/p&gt;

&lt;p&gt;It cannot increase it.&lt;/p&gt;

&lt;p&gt;Raw tokens are shown once.&lt;/p&gt;

&lt;p&gt;Only a hash is stored.&lt;/p&gt;

&lt;p&gt;Revocation and expiry are checked from the database.&lt;/p&gt;

&lt;p&gt;An invalid Bearer token also does not silently fall back to a valid browser cookie.&lt;/p&gt;

&lt;p&gt;Machine identity and human identity remain separate.&lt;/p&gt;




&lt;h2&gt;
  
  
  OIDC SSO
&lt;/h2&gt;

&lt;p&gt;OIDC support was added as an enterprise SSO extension point.&lt;/p&gt;

&lt;p&gt;The flow includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;authorization code
PKCE S256
state
nonce
JWKS signature validation
issuer validation
local durable session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the most important rules is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Identity provider claims authenticate the user. They do not grant Bug Hunter permissions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If an IdP sends something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"roles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that does not make the user an administrator inside Universal Bug Hunter.&lt;/p&gt;

&lt;p&gt;Authorization remains local and capability-based.&lt;/p&gt;

&lt;p&gt;Account linking is also based on trusted OIDC identity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;issuer + subject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;not simply matching an email address.&lt;/p&gt;




&lt;h2&gt;
  
  
  Production migration safety
&lt;/h2&gt;

&lt;p&gt;After building the enterprise control plane, the next question became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can this system actually be operated safely in production?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That started Phase 36.&lt;/p&gt;

&lt;p&gt;Database upgrades are now treated as an operational contract.&lt;/p&gt;

&lt;p&gt;The platform schema is currently v9.&lt;/p&gt;

&lt;p&gt;The migration system includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;preflight
→ backup acknowledgement
→ migration lock
→ durable migration marker
→ stepwise transaction
→ schema version update
→ startup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production database newer than the binary is rejected.&lt;/p&gt;

&lt;p&gt;No downgrade is attempted.&lt;/p&gt;

&lt;p&gt;A failed migration cannot falsely advance the schema version.&lt;/p&gt;

&lt;p&gt;Only one migrator is allowed at a time.&lt;/p&gt;

&lt;p&gt;If a migration is interrupted, the next startup fails closed instead of pretending everything is healthy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Production backup and restore
&lt;/h2&gt;

&lt;p&gt;The latest production-hardening work has focused on backup, restore and disaster recovery.&lt;/p&gt;

&lt;p&gt;This implementation is currently under review before being merged into the main branch.&lt;/p&gt;

&lt;p&gt;The first production model is intentionally conservative:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Backup and restore are offline maintenance operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I chose this instead of pretending the current SQLite architecture supports online distributed snapshots.&lt;/p&gt;

&lt;p&gt;A backup includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;platform database
project data
run artifacts
manifest
checksums
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQLite is copied using the SQLite backup API rather than copying a live WAL database file.&lt;/p&gt;

&lt;p&gt;Included backup files are covered by SHA-256 integrity metadata, together with a deterministic artifact-tree digest.&lt;/p&gt;

&lt;p&gt;The backup format is versioned independently from the platform schema.&lt;/p&gt;




&lt;h2&gt;
  
  
  Restore is also a security operation
&lt;/h2&gt;

&lt;p&gt;A restore is not just copying old data back.&lt;/p&gt;

&lt;p&gt;It can also restore old credential state.&lt;/p&gt;

&lt;p&gt;Imagine this sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T0: backup
T1: API token revoked
T2: restore T0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without additional protection, the old token could become valid again.&lt;/p&gt;

&lt;p&gt;Universal Bug Hunter therefore applies a post-restore credential safety policy.&lt;/p&gt;

&lt;p&gt;By default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;human sessions      → invalidated
OIDC transactions   → invalidated
pending invitations → revoked
API tokens          → invalidated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API tokens can only be preserved through an explicit high-risk operator override.&lt;/p&gt;

&lt;p&gt;Human sessions are always invalidated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Crash-safe restore boundary
&lt;/h2&gt;

&lt;p&gt;Database and artifact directories cannot be atomically replaced together across all environments.&lt;/p&gt;

&lt;p&gt;Instead of pretending otherwise, restore uses a durable state marker.&lt;/p&gt;

&lt;p&gt;The flow looks roughly like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;validate backup
→ verify integrity
→ stage database
→ stage artifacts
→ apply credential safety
→ write restore marker
→ rotate database
→ rotate projects
→ finalize
→ clear marker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the process crashes after the database is swapped but before project artifacts are swapped, the marker remains.&lt;/p&gt;

&lt;p&gt;On the next startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;restore_interrupted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;blocks normal API startup.&lt;/p&gt;

&lt;p&gt;The server does not listen until an operator resolves the recovery state.&lt;/p&gt;

&lt;p&gt;That is much safer than starting with a database from one recovery point and artifacts from another.&lt;/p&gt;




&lt;h2&gt;
  
  
  Integrity is not authenticity
&lt;/h2&gt;

&lt;p&gt;This was another important distinction.&lt;/p&gt;

&lt;p&gt;The backup uses SHA-256 checksums.&lt;/p&gt;

&lt;p&gt;That gives integrity checking against corruption or mismatched files.&lt;/p&gt;

&lt;p&gt;It does not mean the backup is cryptographically authenticated.&lt;/p&gt;

&lt;p&gt;If an attacker can modify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;payload
+
manifest
+
checksums
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;they can potentially produce a different internally consistent backup.&lt;/p&gt;

&lt;p&gt;Signed backups are not part of the current format.&lt;/p&gt;

&lt;p&gt;I prefer documenting that limitation rather than implying stronger security than the system actually provides.&lt;/p&gt;




&lt;h2&gt;
  
  
  Backups are still sensitive data
&lt;/h2&gt;

&lt;p&gt;Another thing I wanted to make explicit is that a backup is not equivalent to a secret-free archive.&lt;/p&gt;

&lt;p&gt;Plaintext provider secrets and environment secret values are excluded, but the platform database can still contain security-sensitive material such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;password hashes
token hashes or digests
identity metadata
session metadata
encrypted application credential material
customer and project data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means backup files should still be protected with restrictive filesystem permissions and treated as sensitive operational data.&lt;/p&gt;

&lt;p&gt;The current implementation uses restrictive permissions where the platform supports them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current production topology
&lt;/h2&gt;

&lt;p&gt;Another thing I wanted to make explicit is the supported deployment topology.&lt;/p&gt;

&lt;p&gt;Today the honest supported model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 API writer instance
+ optional stateless web instances
+ SQLite platform database
+ shared project/artifact storage
+ reverse proxy / TLS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project does not currently claim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;active/active API HA
multi-writer SQLite
distributed job execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those may be future directions, but they are not things I want to pretend already work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where the project is now
&lt;/h2&gt;

&lt;p&gt;Universal Bug Hunter has moved a long way from the version I originally shared.&lt;/p&gt;

&lt;p&gt;The platform now covers several layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application discovery
Test planning
Browser testing
API testing
Visual testing
Accessibility
Quality triage
Regression tracking
Reliability
Performance
CI impact analysis
Project knowledge
Teams and RBAC
Audit
Service accounts
OIDC
Migration safety
Backup and restore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some of the latest backup and restore work is still going through final review before merge, but the broader architecture is already clear.&lt;/p&gt;

&lt;p&gt;The design principle has stayed surprisingly consistent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Automation should reduce uncertainty, not hide it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the system is unsure which tests are affected, it should say so.&lt;/p&gt;

&lt;p&gt;If a regression was not evaluated, it should not show zero.&lt;/p&gt;

&lt;p&gt;If a backup is not authenticated, it should not claim authenticity.&lt;/p&gt;

&lt;p&gt;If the architecture is single-writer, it should not advertise high availability.&lt;/p&gt;

&lt;p&gt;If AI generates something, that does not mean the system should trust or execute it automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;The current production-hardening roadmap continues with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;production configuration validation
health and readiness hardening
operational logging and observability
reference production deployment
multi-instance safety review
operator recovery drills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The platform already has basic health and readiness endpoints.&lt;/p&gt;

&lt;p&gt;The next step is to make their production semantics more explicit and useful for operators and orchestrators.&lt;/p&gt;

&lt;p&gt;A canonical production deployment path is also still planned.&lt;/p&gt;

&lt;p&gt;Local deployment already exists, but I want one clearly documented production reference stack instead of treating development deployment as production guidance.&lt;/p&gt;

&lt;p&gt;There are also features I am intentionally not rushing into yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SCIM
SAML
billing/licensing
multi-IdP
PostgreSQL migration
full active/active HA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would rather finish the operational foundation properly before adding more enterprise surface area.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Building this project has changed how I think about testing infrastructure.&lt;/p&gt;

&lt;p&gt;The difficult part is rarely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can Playwright click this button?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The more interesting questions are:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I trust this result?&lt;/p&gt;

&lt;p&gt;Can another engineer reproduce it?&lt;/p&gt;

&lt;p&gt;What evidence supports the conclusion?&lt;/p&gt;

&lt;p&gt;What happens when two people change the same state?&lt;/p&gt;

&lt;p&gt;What happens when the database upgrade crashes?&lt;/p&gt;

&lt;p&gt;What happens when a backup restores old credentials?&lt;/p&gt;

&lt;p&gt;What happens when the system itself is uncertain?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those questions are what pushed Universal Bug Hunter from a collection of automated tests toward a broader Quality Intelligence platform.&lt;/p&gt;

&lt;p&gt;The project is still evolving, but the direction is much clearer now.&lt;/p&gt;

&lt;p&gt;If you work in QA, DevOps, platform engineering or test infrastructure, I would be interested in feedback on one question in particular:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What would a self-hosted quality platform need to replace the collection of disconnected testing dashboards your team uses today?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>sysops</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>I Built Bug Hunter: A Self-Hosted Full-Stack Testing Tool for Web Apps and APIs</title>
      <dc:creator>Sandro</dc:creator>
      <pubDate>Wed, 15 Jul 2026 13:24:52 +0000</pubDate>
      <link>https://dev.to/xil/i-built-universal-bug-hunter-a-self-hosted-full-stack-testing-tool-for-web-apps-and-apis-4e1o</link>
      <guid>https://dev.to/xil/i-built-universal-bug-hunter-a-self-hosted-full-stack-testing-tool-for-web-apps-and-apis-4e1o</guid>
      <description>&lt;p&gt;Modern web application failures rarely happen in one isolated place.&lt;/p&gt;

&lt;p&gt;A user clicks a button, the frontend sends an API request, the backend returns an unexpected response, and the interface remains stuck in a loading state.&lt;/p&gt;

&lt;p&gt;A health check may still be green. A unit test may still pass. The visible symptom may appear in the browser, while the actual cause is somewhere between the frontend, API, runtime environment, and application configuration.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Universal Bug Hunter&lt;/strong&gt; to make those failures easier to detect, investigate, reproduce, and document.&lt;/p&gt;

&lt;p&gt;It is a self-hosted testing tool that combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;browser testing with Playwright and Chromium,&lt;/li&gt;
&lt;li&gt;direct API smoke testing,&lt;/li&gt;
&lt;li&gt;OpenAPI discovery,&lt;/li&gt;
&lt;li&gt;optional AI-assisted test proposal generation,&lt;/li&gt;
&lt;li&gt;deterministic bug detectors,&lt;/li&gt;
&lt;li&gt;runtime evidence collection,&lt;/li&gt;
&lt;li&gt;finding reproduction,&lt;/li&gt;
&lt;li&gt;static analysis integrations,&lt;/li&gt;
&lt;li&gt;and HTML/JSON reporting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to replace QA engineers, security testers, code review, or existing test suites.&lt;/p&gt;

&lt;p&gt;The goal is more practical:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Execute realistic application flows, preserve useful evidence, and make failures easier to understand and reproduce.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Many automated checks answer only one narrow question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the endpoint return HTTP 200?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is useful, but it does not tell you what happened after the page loaded.&lt;/p&gt;

&lt;p&gt;It does not tell you whether:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the browser logged a JavaScript error,&lt;/li&gt;
&lt;li&gt;an API call returned HTTP 500,&lt;/li&gt;
&lt;li&gt;the interface became stuck,&lt;/li&gt;
&lt;li&gt;a click produced no visible state change,&lt;/li&gt;
&lt;li&gt;the page overflowed horizontally,&lt;/li&gt;
&lt;li&gt;a loading indicator never disappeared,&lt;/li&gt;
&lt;li&gt;a test failed because of the application,&lt;/li&gt;
&lt;li&gt;or the testing engine itself failed operationally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted one workflow that could test a web application from the outside, like a real user, while still collecting enough technical context for a developer or operator to investigate the result.&lt;/p&gt;

&lt;p&gt;That idea became Universal Bug Hunter.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Universal Bug Hunter does
&lt;/h2&gt;

&lt;p&gt;The current workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create project
→ Discover routes
→ Review and approve routes
→ Generate optional AI test proposals
→ Review and approve proposals
→ Compile proposals into scenarios
→ Execute browser and API scenarios
→ Detect findings
→ Reproduce supported findings
→ Generate HTML and JSON reports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The approval steps are intentional.&lt;/p&gt;

&lt;p&gt;Discovery does not automatically execute everything it finds.&lt;/p&gt;

&lt;p&gt;AI does not approve or run its own proposals.&lt;/p&gt;

&lt;p&gt;Compilation creates scenario files, but it does not automatically launch the browser.&lt;/p&gt;

&lt;p&gt;The operator remains in control of what is allowed to run.&lt;/p&gt;




&lt;h2&gt;
  
  
  Browser testing with Playwright
&lt;/h2&gt;

&lt;p&gt;Universal Bug Hunter uses Chromium through Playwright to test an application as a user would experience it.&lt;/p&gt;

&lt;p&gt;Browser scenarios can navigate through the application, interact with visible elements, verify UI state, and capture screenshots.&lt;/p&gt;

&lt;p&gt;A simple scenario can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;navigate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/login&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;waitForVisible&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Username&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;captureScreenshot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;login-page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During execution, Bug Hunter can collect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;browser console messages,&lt;/li&gt;
&lt;li&gt;uncaught page errors,&lt;/li&gt;
&lt;li&gt;failed network requests,&lt;/li&gt;
&lt;li&gt;HTTP 4xx and 5xx responses,&lt;/li&gt;
&lt;li&gt;screenshots,&lt;/li&gt;
&lt;li&gt;DOM snapshots,&lt;/li&gt;
&lt;li&gt;navigation information,&lt;/li&gt;
&lt;li&gt;and other runtime evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current deterministic detector set includes checks such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;console-error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;page-error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;failed-request&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http-error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;blank-page&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;horizontal-overflow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stuck-loader&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;no-state-change&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These detectors do not depend on an LLM. They evaluate collected evidence using predictable rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  Direct API testing
&lt;/h2&gt;

&lt;p&gt;Browser testing only covers backend requests that are actually triggered by the frontend.&lt;/p&gt;

&lt;p&gt;To improve backend coverage, I added direct HTTP scenarios.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/ready&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;assertHttpStatus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A POST scenario can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;httpPost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/api/auth/login&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
      &lt;span class="na"&gt;jsonBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;assertHttpStatus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browser scenarios and HTTP-only scenarios use separate execution paths.&lt;/p&gt;

&lt;p&gt;A composite orchestrator can still run both types as part of the same batch.&lt;/p&gt;

&lt;p&gt;This keeps browser execution and direct API execution clearly separated while allowing them to contribute to the same project-level test workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  OpenAPI discovery and API smoke generation
&lt;/h2&gt;

&lt;p&gt;For applications that expose an OpenAPI specification, Bug Hunter can import the specification and build an inventory of API operations.&lt;/p&gt;

&lt;p&gt;The basic flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OpenAPI specification
→ operation discovery
→ generated API smoke scenarios
→ scenario approval
→ execution
→ report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current generator supports basic GET and POST smoke coverage.&lt;/p&gt;

&lt;p&gt;For example, an imported API specification can produce scenarios for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /health
GET /ready
POST /api/auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is intentionally conservative.&lt;/p&gt;

&lt;p&gt;The current version does not yet attempt to generate complex destructive requests automatically.&lt;/p&gt;

&lt;p&gt;Support for OpenAPI parameters, authentication profiles, request body generation, response schema validation, and negative API testing is planned for future versions.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI-assisted exploration with human approval
&lt;/h2&gt;

&lt;p&gt;AI exploration is optional.&lt;/p&gt;

&lt;p&gt;When enabled, an LLM receives a controlled representation of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;approved routes,&lt;/li&gt;
&lt;li&gt;discovered interactions,&lt;/li&gt;
&lt;li&gt;existing scenarios,&lt;/li&gt;
&lt;li&gt;and detected coverage gaps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can propose read-only test scenarios using a restricted action set such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;navigate,&lt;/li&gt;
&lt;li&gt;click,&lt;/li&gt;
&lt;li&gt;assert visible,&lt;/li&gt;
&lt;li&gt;assert URL,&lt;/li&gt;
&lt;li&gt;capture screenshot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every proposal passes through a deterministic safety pipeline.&lt;/p&gt;

&lt;p&gt;A proposal must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;target an approved route,&lt;/li&gt;
&lt;li&gt;use only permitted actions,&lt;/li&gt;
&lt;li&gt;remain read-only,&lt;/li&gt;
&lt;li&gt;stay within configured step limits,&lt;/li&gt;
&lt;li&gt;avoid credentials and sensitive values,&lt;/li&gt;
&lt;li&gt;and conform to a strict schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Passing this validation does not mean the proposal is automatically approved.&lt;/p&gt;

&lt;p&gt;The workflow remains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI-generated
≠ safe by default

Safety accepted
≠ human approved

Human approved
≠ automatically executed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The operator reviews each accepted proposal and decides whether it should be approved, rejected, or compiled into a scenario.&lt;/p&gt;




&lt;h2&gt;
  
  
  Findings, evidence, and reproduction
&lt;/h2&gt;

&lt;p&gt;A useful bug report should not only say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A request failed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should help answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which scenario triggered the problem?&lt;/li&gt;
&lt;li&gt;Which route was active?&lt;/li&gt;
&lt;li&gt;Which action happened before the failure?&lt;/li&gt;
&lt;li&gt;What did the browser log?&lt;/li&gt;
&lt;li&gt;Which request failed?&lt;/li&gt;
&lt;li&gt;Was the behavior reproduced?&lt;/li&gt;
&lt;li&gt;Is there a screenshot?&lt;/li&gt;
&lt;li&gt;Is there a DOM snapshot?&lt;/li&gt;
&lt;li&gt;Is the finding eligible for reporting?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bug Hunter stores evidence separately from project configuration.&lt;/p&gt;

&lt;p&gt;A typical run can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;batch-report.json
batch-report.html
batch-state.json
runs/
  run-summary.json
  findings.json
  evidence/
  screenshots/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When supported, a finding can be replayed in a fresh browser session.&lt;/p&gt;

&lt;p&gt;This helps distinguish a reproducible application issue from one-time browser or environment noise.&lt;/p&gt;




&lt;h2&gt;
  
  
  Execution success is not the same as a passing test result
&lt;/h2&gt;

&lt;p&gt;This distinction became one of the most important parts of the system.&lt;/p&gt;

&lt;p&gt;A job can complete successfully from an infrastructure perspective while the tested application still produces findings.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execution job: completed
Scenarios executed: 6
Passed: 3
With findings: 3
Operational failures: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the execution engine completed,&lt;/li&gt;
&lt;li&gt;all six scenarios were executed,&lt;/li&gt;
&lt;li&gt;three scenarios produced no findings,&lt;/li&gt;
&lt;li&gt;three scenarios produced detector findings,&lt;/li&gt;
&lt;li&gt;and the runner itself did not fail operationally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is different from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Operational failures: 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An operational failure may indicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the browser could not start,&lt;/li&gt;
&lt;li&gt;navigation timed out,&lt;/li&gt;
&lt;li&gt;a required element could not be found,&lt;/li&gt;
&lt;li&gt;the scenario could not complete,&lt;/li&gt;
&lt;li&gt;or the runtime environment failed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am continuing to improve this distinction in the operator dashboard so that &lt;code&gt;Completed&lt;/code&gt;, &lt;code&gt;Passed&lt;/code&gt;, &lt;code&gt;With findings&lt;/code&gt;, and &lt;code&gt;Operational failure&lt;/code&gt; cannot be confused with each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing localhost applications from Docker
&lt;/h2&gt;

&lt;p&gt;One of my main requirements was testing applications before they are publicly deployed.&lt;/p&gt;

&lt;p&gt;Bug Hunter can run locally through Docker while testing another application that is running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;directly on the Windows host,&lt;/li&gt;
&lt;li&gt;inside another Docker Compose service,&lt;/li&gt;
&lt;li&gt;on a private development address,&lt;/li&gt;
&lt;li&gt;or on a regular staging URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From inside a container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;refers to that container itself.&lt;/p&gt;

&lt;p&gt;For an application running directly on the Windows host, Bug Hunter uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://host.docker.internal:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A local target can be configured like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:3000&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
  &lt;span class="na"&gt;allowedDomains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;host.docker.internal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A full-stack project can define separate frontend and API targets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fullstack&lt;/span&gt;

&lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:3000&lt;/span&gt;

  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://host.docker.internal:8787&lt;/span&gt;
    &lt;span class="na"&gt;healthPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/ready&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Private and loopback targets are not enabled globally.&lt;/p&gt;

&lt;p&gt;They must be explicitly allowed through the local environment and network policy configuration.&lt;/p&gt;

&lt;p&gt;The same allowlist logic is applied to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;browser navigation,&lt;/li&gt;
&lt;li&gt;redirects,&lt;/li&gt;
&lt;li&gt;direct HTTP scenarios,&lt;/li&gt;
&lt;li&gt;and OpenAPI retrieval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This preserves the SSRF protection while still allowing intentional localhost testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Static analysis integrations
&lt;/h2&gt;

&lt;p&gt;Bug Hunter also includes a static analysis layer with provider adapters for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Semgrep&lt;/strong&gt; for SAST,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trivy&lt;/strong&gt; for dependency and filesystem analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The static analysis command writes normalized results into the project workspace.&lt;/p&gt;

&lt;p&gt;If a configured tool is not installed, the pipeline reports that the provider is unavailable instead of crashing the entire workflow.&lt;/p&gt;

&lt;p&gt;This is still an early integration.&lt;/p&gt;

&lt;p&gt;The goal is not to replace dedicated Semgrep or Trivy workflows.&lt;/p&gt;

&lt;p&gt;The longer-term goal is to present dynamic browser findings, API findings, dependency findings, and static analysis results within the same project context.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Universal Bug Hunter is a TypeScript monorepo built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 22&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;pnpm workspaces&lt;/li&gt;
&lt;li&gt;Fastify&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Playwright&lt;/li&gt;
&lt;li&gt;Chromium&lt;/li&gt;
&lt;li&gt;TanStack Query&lt;/li&gt;
&lt;li&gt;Zod&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;OpenAI as an optional exploration provider&lt;/li&gt;
&lt;li&gt;Semgrep&lt;/li&gt;
&lt;li&gt;Trivy&lt;/li&gt;
&lt;li&gt;HTML and JSON reporters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system is divided into focused packages for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;core domain models,&lt;/li&gt;
&lt;li&gt;configuration and validation,&lt;/li&gt;
&lt;li&gt;browser execution,&lt;/li&gt;
&lt;li&gt;direct HTTP execution,&lt;/li&gt;
&lt;li&gt;route discovery,&lt;/li&gt;
&lt;li&gt;OpenAPI discovery,&lt;/li&gt;
&lt;li&gt;AI exploration,&lt;/li&gt;
&lt;li&gt;evidence storage,&lt;/li&gt;
&lt;li&gt;deterministic detectors,&lt;/li&gt;
&lt;li&gt;finding reproduction,&lt;/li&gt;
&lt;li&gt;scenario execution,&lt;/li&gt;
&lt;li&gt;reporting,&lt;/li&gt;
&lt;li&gt;API services,&lt;/li&gt;
&lt;li&gt;CLI commands,&lt;/li&gt;
&lt;li&gt;and the web operator interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I intentionally avoided placing browser control, filesystem access, AI calls, HTTP testing, reporting, and security policy inside one large service.&lt;/p&gt;

&lt;p&gt;Testing systems become difficult to maintain when every responsibility is tightly coupled to the runner.&lt;/p&gt;




&lt;h2&gt;
  
  
  The operator workflow
&lt;/h2&gt;

&lt;p&gt;The web interface follows the project lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Overview
→ Discovery
→ Exploration
→ Proposals
→ Scenarios
→ Runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The operator can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a project,&lt;/li&gt;
&lt;li&gt;start route discovery,&lt;/li&gt;
&lt;li&gt;approve or reject discovered routes,&lt;/li&gt;
&lt;li&gt;start optional AI exploration,&lt;/li&gt;
&lt;li&gt;review proposals,&lt;/li&gt;
&lt;li&gt;approve or reject proposals,&lt;/li&gt;
&lt;li&gt;compile approved proposals,&lt;/li&gt;
&lt;li&gt;run all approved scenarios,&lt;/li&gt;
&lt;li&gt;run selected scenarios,&lt;/li&gt;
&lt;li&gt;inspect execution history,&lt;/li&gt;
&lt;li&gt;review findings,&lt;/li&gt;
&lt;li&gt;and download HTML or JSON reports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interface is deliberately operator-focused.&lt;/p&gt;

&lt;p&gt;It does not expose target URL changes, browser configuration, credentials, or reporting configuration during scenario execution.&lt;/p&gt;

&lt;p&gt;Those values remain controlled by the project manifest and backend policy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Local verification
&lt;/h2&gt;

&lt;p&gt;I tested the current full-stack workflow in two different ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Host execution
&lt;/h3&gt;

&lt;p&gt;The first test executed directly from the host against the local web UI and API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Selected: 6
Passed: 6
Operational failures: 0
Exit code: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The batch contained:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;three browser smoke scenarios,&lt;/li&gt;
&lt;li&gt;three direct API smoke scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docker-to-host execution
&lt;/h3&gt;

&lt;p&gt;The second test ran from the Docker API container against the Windows host through &lt;code&gt;host.docker.internal&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Selected: 6
Executed: 6
Passed: 3
With findings: 3
Operational failures: 0
Exit code: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three API scenarios passed.&lt;/p&gt;

&lt;p&gt;The three browser scenarios completed operationally but produced console or network findings.&lt;/p&gt;

&lt;p&gt;This demonstrated an important behavior:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The execution engine can complete correctly while the tested application still produces reportable findings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An exit code of &lt;code&gt;1&lt;/code&gt; does not necessarily mean the testing infrastructure crashed.&lt;/p&gt;

&lt;p&gt;It can mean that relevant findings were detected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current limitations
&lt;/h2&gt;

&lt;p&gt;Universal Bug Hunter is still evolving.&lt;/p&gt;

&lt;p&gt;The current version has several known limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;job state is stored in memory and is lost after an API restart,&lt;/li&gt;
&lt;li&gt;authentication currently supports one local admin account,&lt;/li&gt;
&lt;li&gt;the execution queue runs inside one Node.js process,&lt;/li&gt;
&lt;li&gt;API smoke generation has limited OpenAPI parameter and body support,&lt;/li&gt;
&lt;li&gt;HTTP-only scenarios do not yet have the same reproduction flow as browser scenarios,&lt;/li&gt;
&lt;li&gt;backend logs and distributed traces are not yet correlated with browser requests,&lt;/li&gt;
&lt;li&gt;static analysis integrations are still basic,&lt;/li&gt;
&lt;li&gt;artifact retention and cleanup need stronger lifecycle controls,&lt;/li&gt;
&lt;li&gt;concurrency and browser resource limits need further hardening,&lt;/li&gt;
&lt;li&gt;and deployment is currently focused on local self-hosting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I prefer being clear about these limitations.&lt;/p&gt;

&lt;p&gt;An automated testing tool should not create false confidence.&lt;/p&gt;

&lt;p&gt;A successful run does not prove that an application has no bugs.&lt;/p&gt;

&lt;p&gt;It only proves that the selected scenarios completed under the tested conditions without producing findings recognized by the enabled detectors.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I am improving next
&lt;/h2&gt;

&lt;p&gt;The next areas I am working on include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;job concurrency and queue limits,&lt;/li&gt;
&lt;li&gt;browser session limits,&lt;/li&gt;
&lt;li&gt;artifact retention and cleanup,&lt;/li&gt;
&lt;li&gt;structured operational logging,&lt;/li&gt;
&lt;li&gt;better runtime status visibility,&lt;/li&gt;
&lt;li&gt;OpenAPI parameter support,&lt;/li&gt;
&lt;li&gt;request body generation,&lt;/li&gt;
&lt;li&gt;authentication profiles for API scenarios,&lt;/li&gt;
&lt;li&gt;negative API test generation,&lt;/li&gt;
&lt;li&gt;response schema assertions,&lt;/li&gt;
&lt;li&gt;backend log and trace correlation,&lt;/li&gt;
&lt;li&gt;and clearer result summaries in the operator dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One longer-term goal is to correlate the complete path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser action
→ frontend state
→ API request
→ backend response
→ log or trace
→ one combined finding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That would make Bug Hunter more useful than a collection of disconnected browser, API, and static checks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this project matters to me
&lt;/h2&gt;

&lt;p&gt;I built Universal Bug Hunter as a practical QA automation, DevOps, and DevSecOps project.&lt;/p&gt;

&lt;p&gt;It combines several areas I regularly work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;browser automation,&lt;/li&gt;
&lt;li&gt;API testing,&lt;/li&gt;
&lt;li&gt;TypeScript,&lt;/li&gt;
&lt;li&gt;Docker,&lt;/li&gt;
&lt;li&gt;application security,&lt;/li&gt;
&lt;li&gt;evidence collection,&lt;/li&gt;
&lt;li&gt;reporting,&lt;/li&gt;
&lt;li&gt;CI/CD design,&lt;/li&gt;
&lt;li&gt;and system architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most interesting part was not simply making Playwright click through a page.&lt;/p&gt;

&lt;p&gt;The harder questions were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What should the system be allowed to execute?&lt;/li&gt;
&lt;li&gt;How do you prevent AI proposals from bypassing safety rules?&lt;/li&gt;
&lt;li&gt;How do you distinguish a product bug from an environment problem?&lt;/li&gt;
&lt;li&gt;How do you preserve useful evidence without leaking secrets?&lt;/li&gt;
&lt;li&gt;How do you reproduce findings deterministically?&lt;/li&gt;
&lt;li&gt;How do you test localhost applications safely from Docker?&lt;/li&gt;
&lt;li&gt;How do you explain that a job completed even when tests found problems?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those questions shaped the architecture more than the UI itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;p&gt;Universal Bug Hunter currently runs as a local, self-hosted testing environment.&lt;/p&gt;

&lt;p&gt;I am testing it against local applications before considering a public deployment.&lt;/p&gt;

&lt;p&gt;The complete current flow works from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;URL discovery
→ route approval
→ optional AI exploration
→ proposal review
→ scenario compilation
→ browser and API execution
→ findings
→ report download
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am sharing the project to get feedback from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QA engineers,&lt;/li&gt;
&lt;li&gt;developers,&lt;/li&gt;
&lt;li&gt;DevOps engineers,&lt;/li&gt;
&lt;li&gt;platform engineers,&lt;/li&gt;
&lt;li&gt;and security practitioners.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would especially appreciate feedback on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether the workflow is understandable,&lt;/li&gt;
&lt;li&gt;whether findings contain enough evidence,&lt;/li&gt;
&lt;li&gt;whether operational failures and application findings are clearly separated,&lt;/li&gt;
&lt;li&gt;which API checks would be most useful,&lt;/li&gt;
&lt;li&gt;whether the approval workflow feels too strict or appropriately safe,&lt;/li&gt;
&lt;li&gt;and what would make the tool useful in a real development workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Universal Bug Hunter is still a work in progress, but the core idea is already clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find problems through realistic application flows, preserve the evidence, and make the result easier to understand and reproduce.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>I Built PentestScan: A Simple Web &amp; API Security Scanner for Developers and Small Teams</title>
      <dc:creator>Sandro</dc:creator>
      <pubDate>Mon, 18 May 2026 06:30:58 +0000</pubDate>
      <link>https://dev.to/xil/i-built-pentestscan-a-simple-web-api-security-scanner-for-developers-and-small-teams-38km</link>
      <guid>https://dev.to/xil/i-built-pentestscan-a-simple-web-api-security-scanner-for-developers-and-small-teams-38km</guid>
      <description>&lt;p&gt;Building security tools always sounds more impressive than it really is at the beginning.&lt;/p&gt;

&lt;p&gt;In my case, PentestScan started as a practical idea:&lt;br&gt;
I wanted to build a simple Web &amp;amp; API security scanner that could help developers, small teams, and DevOps engineers catch common security issues earlier - before an application reaches production.&lt;/p&gt;

&lt;p&gt;Not as a replacement for professional penetration testing.&lt;br&gt;
Not as a magic “find everything” scanner.&lt;br&gt;
But it is a practical DevSecOps tool that gives fast, understandable feedback.&lt;/p&gt;

&lt;p&gt;The problem I wanted to solve was simple:&lt;/p&gt;

&lt;p&gt;A lot of small teams do not have a dedicated AppSec engineer.&lt;br&gt;
Security reviews often happen too late.&lt;br&gt;
Reports from bigger tools can be too complex, too noisy, or too expensive for early-stage projects.&lt;br&gt;
And developers usually need something direct:&lt;/p&gt;

&lt;p&gt;What is wrong?&lt;br&gt;
Why does it matter?&lt;br&gt;
How can I fix it?&lt;/p&gt;

&lt;p&gt;That is the direction I took with PentestScan.&lt;/p&gt;

&lt;p&gt;What PentestScan does&lt;/p&gt;

&lt;p&gt;PentestScan is a Web &amp;amp; API security scanner focused on practical checks around common security weaknesses.&lt;/p&gt;

&lt;p&gt;The current version is built around:&lt;/p&gt;

&lt;p&gt;Web application scanning&lt;br&gt;
API security testing&lt;br&gt;
OWASP Top 10 related checks&lt;br&gt;
Security headers analysis&lt;br&gt;
JWT and session-related checks&lt;br&gt;
Basic exposure detection&lt;br&gt;
Report generation&lt;br&gt;
DevSecOps-friendly workflow&lt;/p&gt;

&lt;p&gt;The goal is not to overload the user with hundreds of unclear findings.&lt;/p&gt;

&lt;p&gt;The goal is to provide a clean report that helps someone understand the risk and take action.&lt;/p&gt;

&lt;p&gt;Tech stack&lt;/p&gt;

&lt;p&gt;The project is built with a simple and practical stack:&lt;/p&gt;

&lt;p&gt;Python&lt;br&gt;
FastAPI&lt;br&gt;
Docker&lt;br&gt;
Nginx&lt;br&gt;
HTML reporting&lt;br&gt;
API-first backend structure&lt;br&gt;
Security-focused scanning modules&lt;/p&gt;

&lt;p&gt;I wanted the architecture to stay modular because security tooling can become messy very quickly if everything is placed into one large script.&lt;/p&gt;

&lt;p&gt;So the scanner is organized around separate modules and checks, with the idea that new functionality can be added gradually without breaking the existing structure.&lt;/p&gt;

&lt;p&gt;Why I built it&lt;/p&gt;

&lt;p&gt;I built PentestScan mainly as a hands-on DevSecOps project.&lt;/p&gt;

&lt;p&gt;I wanted to combine several areas that I work with and care about:&lt;/p&gt;

&lt;p&gt;application security&lt;br&gt;
backend development&lt;br&gt;
automation&lt;br&gt;
Linux deployment&lt;br&gt;
Docker-based services&lt;br&gt;
CI/CD security thinking&lt;br&gt;
security reporting&lt;/p&gt;

&lt;p&gt;One thing I learned while building it is that detection is only one part of the problem.&lt;/p&gt;

&lt;p&gt;The harder part is explaining the finding in a useful way.&lt;/p&gt;

&lt;p&gt;A security report should not only say:&lt;/p&gt;

&lt;p&gt;Missing security header detected.&lt;/p&gt;

&lt;p&gt;It should explain:&lt;/p&gt;

&lt;p&gt;what was detected,&lt;br&gt;
why it matters,&lt;br&gt;
how it could be abused,&lt;br&gt;
how serious it is,&lt;br&gt;
and what the developer can do next.&lt;/p&gt;

&lt;p&gt;That became one of the most important ideas behind the project.&lt;/p&gt;

&lt;p&gt;What I am trying to improve&lt;/p&gt;

&lt;p&gt;PentestScan is still evolving.&lt;/p&gt;

&lt;p&gt;Some of the things I am working on or planning to improve are:&lt;/p&gt;

&lt;p&gt;better API scanning&lt;br&gt;
cleaner report structure&lt;br&gt;
more contextual findings&lt;br&gt;
CI/CD integration&lt;br&gt;
better severity scoring&lt;br&gt;
improved attack-path style explanations&lt;br&gt;
more useful remediation guidance&lt;br&gt;
public sample reports&lt;/p&gt;

&lt;p&gt;I am also trying to keep the tool realistic.&lt;/p&gt;

&lt;p&gt;Security scanners can easily create false confidence.&lt;br&gt;
Just because a scanner does not find something does not mean the application is secure.&lt;/p&gt;

&lt;p&gt;So I see PentestScan as a first security layer - something that can help teams catch obvious and common issues earlier, not as a full replacement for manual testing.&lt;/p&gt;

&lt;p&gt;Current version&lt;/p&gt;

&lt;p&gt;The project is currently available for free here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pentestscan.app/" rel="noopener noreferrer"&gt;https://pentestscan.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before trying the scanner, you can also check a public sample report:&lt;/p&gt;

&lt;p&gt;Sample vulnerability report:&lt;br&gt;&lt;br&gt;
&lt;a href="https://pentestscan.app/api/v1/public/marketing/vulnerability_report.html" rel="noopener noreferrer"&gt;https://pentestscan.app/api/v1/public/marketing/vulnerability_report.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am sharing PentestScan publicly to get feedback from developers, DevOps engineers, and security people.&lt;/p&gt;

&lt;p&gt;I would especially appreciate feedback on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;report structure and clarity,&lt;/li&gt;
&lt;li&gt;usefulness of the findings,&lt;/li&gt;
&lt;li&gt;scanning flow,&lt;/li&gt;
&lt;li&gt;missing checks,&lt;/li&gt;
&lt;li&gt;and whether the tool feels useful for small teams or solo developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is still a work in progress, but it has already been a valuable learning experience in building security tooling that is not only technical but also understandable and useful.&lt;/p&gt;

&lt;p&gt;That, for me, is the main point of PentestScan:&lt;/p&gt;

&lt;p&gt;help developers see security issues earlier, understand them faster, and fix them with less friction.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
  </channel>
</rss>
