<?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: Allura Gensin</title>
    <description>The latest articles on DEV Community by Allura Gensin (@alluragensin).</description>
    <link>https://dev.to/alluragensin</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%2F4079472%2F6fb71c26-959d-4cf0-bb1c-e35451cc6865.png</url>
      <title>DEV Community: Allura Gensin</title>
      <link>https://dev.to/alluragensin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alluragensin"/>
    <language>en</language>
    <item>
      <title>A small GitHub Action for checking public launch paths without turning CI into a browser bot</title>
      <dc:creator>Allura Gensin</dc:creator>
      <pubDate>Sat, 15 Aug 2026 20:57:44 +0000</pubDate>
      <link>https://dev.to/alluragensin/a-small-github-action-for-checking-public-launch-paths-without-turning-ci-into-a-browser-bot-30lj</link>
      <guid>https://dev.to/alluragensin/a-small-github-action-for-checking-public-launch-paths-without-turning-ci-into-a-browser-bot-30lj</guid>
      <description>&lt;p&gt;Launch-readiness checks often start with a harmless question: can an ordinary&lt;br&gt;
visitor reach the action we expect? It is tempting to answer that by putting a&lt;br&gt;
full browser, credentials, and a broad crawler into CI. That creates a much&lt;br&gt;
larger security and privacy surface than the question requires.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Public-Path Evidence Check&lt;/strong&gt; as a deliberately smaller alternative.&lt;br&gt;
It accepts one to five explicit public HTTPS URLs and writes a private Markdown&lt;br&gt;
report inside the GitHub-hosted runner. It performs GET requests only. It does&lt;br&gt;
not execute JavaScript, follow redirects, retain cookies, submit forms, log in,&lt;br&gt;
or upload the report.&lt;/p&gt;

&lt;p&gt;The Action is free and open source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/marketplace/actions/public-path-evidence-check" rel="noopener noreferrer"&gt;GitHub Marketplace listing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Allura-Gensin/public-path-evidence-audit-starter" rel="noopener noreferrer"&gt;Source, worksheets, and example workflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The design constraint: observation, not interaction
&lt;/h2&gt;

&lt;p&gt;The useful boundary is not “read-only browser automation.” A browser can still&lt;br&gt;
send cookies, execute scripts, follow a redirect into a private service, or&lt;br&gt;
trigger behavior during page load.&lt;/p&gt;

&lt;p&gt;This Action instead captures a narrow set of facts from explicitly supplied&lt;br&gt;
routes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the route requested;&lt;/li&gt;
&lt;li&gt;the final HTTP status;&lt;/li&gt;
&lt;li&gt;the reported content type;&lt;/li&gt;
&lt;li&gt;whether the bounded response looked like HTML; and&lt;/li&gt;
&lt;li&gt;a small set of visible-document signals suitable for a review worksheet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is evidence, not a verdict. A 200 response does not prove that a&lt;br&gt;
launch path is usable, accessible, compliant, secure, or likely to convert. It&lt;br&gt;
only gives a reviewer a reproducible starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  A minimal workflow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Public path evidence&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;inspect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&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;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allura-Gensin/public-path-evidence-audit-starter@af85ce58fa071c56e4d16d19b77c19a2a69dbd9e&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;evidence&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;urls-json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;["https://example.com/",&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://example.com/pricing"]'&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;Use the private report in this job&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;REPORT_PATH&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.evidence.outputs.report-path }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test -s "$REPORT_PATH"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example pins the reviewed commit rather than a moving tag. The Action&lt;br&gt;
requests no repository permission and exposes the report path plus route and&lt;br&gt;
HTML counts as outputs. It does not automatically upload an artifact because&lt;br&gt;
publication should be an explicit caller decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  The less-obvious safety work
&lt;/h2&gt;

&lt;p&gt;Restricting the input to HTTPS is not enough. A CI runner can reach addresses&lt;br&gt;
that should never become crawler targets, and DNS can change between&lt;br&gt;
validation and connection.&lt;/p&gt;

&lt;p&gt;The implementation therefore rejects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP literals, credentials, fragments, query strings, and non-standard ports;&lt;/li&gt;
&lt;li&gt;private, loopback, link-local, multicast, documentation, benchmarking, and
other special-purpose IPv4 and IPv6 ranges;&lt;/li&gt;
&lt;li&gt;hostnames with mixed public and non-public DNS answers;&lt;/li&gt;
&lt;li&gt;redirects; and&lt;/li&gt;
&lt;li&gt;self-hosted runners.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It resolves the hostname, caps the accepted address set, then verifies that the&lt;br&gt;
connected peer is one of the approved public addresses. TLS still uses the&lt;br&gt;
original hostname for SNI and certificate validation.&lt;/p&gt;

&lt;p&gt;Resource limits matter as much as address validation. Each route receives one&lt;br&gt;
15-second deadline covering DNS, connection, TLS, headers, and body. The whole&lt;br&gt;
run is capped at 60 seconds. Responses stop at 1 MiB, and cumulative status-line&lt;br&gt;
plus header bytes stop at 64 KiB. The report is created once under&lt;br&gt;
&lt;code&gt;$RUNNER_TEMP&lt;/code&gt; with private permissions; a pre-existing path is refused.&lt;/p&gt;

&lt;p&gt;These limits do not make arbitrary network automation safe. They make this one&lt;br&gt;
small public-observation task easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Action intentionally does not do
&lt;/h2&gt;

&lt;p&gt;It does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;test forms, authentication, checkout, or account creation;&lt;/li&gt;
&lt;li&gt;make purchases or enter data;&lt;/li&gt;
&lt;li&gt;run a vulnerability scan;&lt;/li&gt;
&lt;li&gt;claim accessibility, privacy, SEO, performance, or compliance certification;&lt;/li&gt;
&lt;li&gt;infer conversion loss or revenue impact; or&lt;/li&gt;
&lt;li&gt;publish its report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those exclusions are product features. They keep a lightweight launch check&lt;br&gt;
from silently expanding into production interaction or security testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical review loop
&lt;/h2&gt;

&lt;p&gt;The repository includes CSV worksheets and a short checklist for the human&lt;br&gt;
part of the review. A useful loop is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name one visitor action.&lt;/li&gt;
&lt;li&gt;List no more than five public routes needed to reach it.&lt;/li&gt;
&lt;li&gt;Capture the bounded technical evidence.&lt;/li&gt;
&lt;li&gt;Review desktop and mobile presentation separately.&lt;/li&gt;
&lt;li&gt;Record observations apart from hypotheses and recommendations.&lt;/li&gt;
&lt;li&gt;Treat a clean path as a valid result; do not manufacture findings.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is also a &lt;a href="https://offers.allurelabs.ai/public-path-checklist/" rel="noopener noreferrer"&gt;free browser-sized public-path checklist&lt;/a&gt;&lt;br&gt;
for teams that do not want to add anything to CI.&lt;/p&gt;

&lt;p&gt;I would welcome feedback on the boundary itself: which facts are valuable&lt;br&gt;
enough to capture while keeping the Action credential-free, non-interactive,&lt;br&gt;
and safe for a standard GitHub-hosted runner?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I used an AI coding assistant while implementing, testing, and&lt;br&gt;
editing this project and article. I reviewed the resulting code, claims, and&lt;br&gt;
published material.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>github</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
