Cloud Crawler: HCW-CloudCrawler_App and HCW-CloudCrawler_AddOn¶
The fourth pair of the App-to-AddOn program. Its catalogue row was
coming from 2026-10-24 and is available from the second of the two pull
requests for #1357:
/tools/cloud-crawler frames the AddOn and the Tools menu lists it, from the
day the owner deploys the site (the website is deployed by hand, so merging is
not enough). The first
pull request (#1411)
made the host able to run the container and the site's backend able to reach it,
and the row stayed coming until the container ran and the status route
answered. The site-side row was added when the pair was introduced, ahead of a
release, the same way the network and cloud assessment rows were.
| Fact | Value |
|---|---|
| Catalogue id | cloud-crawler |
| Site route | /tools/cloud-crawler (in the Tools menu once the site is deployed) |
| AddOn origin | https://cloud-crawler.lab.hybridcloudworks.com (the wildcard *.lab name resolves to the lab host's address; read from a public resolver on 2026-10-26) |
| Image | docker.io/hybridcloudworks/img-cc-lab-addon:v0.2.0, index digest sha256:5a43c90bda9bed1d3472847f492b7c05405e6a6ce2d4aa7f4d9b519bb72daf28 (linux/amd64), published by the AddOn's publish-images.yml on its v0.2.0 tag (run 40318349978); the build attestation verifies against HCW-CloudCrawler_AddOn and the signer is that workflow at refs/tags/v0.2.0 |
| Lab host port | 18084 on 127.0.0.1 (the website's call, per the AddOn's ADR 0003; the next after the Cloud Assessor's 18083) |
| Lab host row | in lab-host/ansible/group_vars/all.yml since #1411; the host runs it: the owner reported running the playbook on 2026-10-26 and a session read the container's health through the status route afterwards (below). The steps are the runbook's |
| Row status | available; the pane is granted downloads and clipboard-write, not navigate (why, below the table) |
| Status proxy | GET /api/public/addons/cloud-crawler/status, reading ADDON_CLOUD_CRAWLER_URL (a plain app setting in infra/functionapp.tf, applied by the owner's HCP Terraform run). On 2026-10-26 (its asOf was 16:06Z) it answered configured: true, reachable: true, version 0.2.0, edition lab, with the upload capabilities listed in the AddOn's guide |
| Settings prefix | CC_ (the AddOn's .env.example) |
| Vault key | vault_addon_cloud_crawler_turnstile_secret (the AddOn's ADR 0003); the owner states it is in the host's vault, which no session can read. Whether it pairs with the widget's site key is proved only by one real upload (below) |
| Pull requests | App: https://github.com/saulpatinojr/HCW-CloudCrawler_App; AddOn: https://github.com/saulpatinojr/HCW-CloudCrawler_AddOn |
Why the pane gets downloads and clipboard-write and not navigate. The
rule is that a pane is granted what it uses (website issue
#1354). The
pane's own code (web/app.js and web/index.html in the AddOn, read on
2026-10-26) saves the report and the sample files through download links and a
file made in the browser, which needs downloads; it copies the report with the
clipboard's write call, which needs clipboard-write and never the read call;
and it has no code that sends a navigate message, opens a window or changes the
page's address. It sends the site only its own state (loading, ready,
working, unavailable).
Where it stands, read on 2026-10-26¶
- The App has released.
v0.1.0was released on 2026-10-26 and the AddOn adopted its engine unchanged. - The AddOn has an image with the upload route.
v0.1.0(engine adopted, no upload route) andv0.2.0(the first with the upload route) are on Docker Hub; onlyv0.2.0is pinned here, because a row that promises an upload needs an image that can take one. The digest and the attestation check are in the tracking issue and were re-checked for #1357 (gh attestation verifyexited 0, and the signing certificate namespublish-images.ymlatrefs/tags/v0.2.0). The AddOn's GitHub Release pages forv0.1.0andv0.2.0were published on 2026-10-26 (releases). - The host runs it. The owner reported running the vault check and the
lab-host playbook on 2026-10-26; a session's note on #1357
records it (the pasted
PLAY RECAPshowed the run completed, and the host recorded commitcab8bcc4). HCP Terraform's commit status on the merge commit of #1411 read Success that day, and a session then read the status route (configured: true, reachable: true, version 0.2.0) and the pane's address, which answers withX-Addon-Id: cloud-crawlerand aframe-ancestorsthat allows the pane itself and the site's two origins only. The vault key and the certificate were not read by any session. The status answer and the pane's headers show the container started and the name is served over a certificate the site's backend accepts. The key was not empty (the playbook stops otherwise), but whether it is the right secret for the widget is not known until the first real upload (below). - Terraform reading is not in this image, so the row does not promise it.
The upload accepts a Terraform state or plan, but the engine 0.1.0 does not
read it, so a claim about Terraform stays
unknown(the AddOn'sdocs/api.md, "The upload"). The row's first summary said "or your Terraform"; the flip removes those words and theterraformentry from the row'stechnologylist. Restore both when the AddOn ships an engine that reads Terraform (the engine change is merged upstream, HCW-CloudCrawler_App#60 for #54, but the App has no release afterv0.1.0and the AddOn has not taken a new engine). The AddOn tracks this as HCW-CloudCrawler_AddOn#29, and its integration guide holds the same row, field by field. - Not verified by any session when the row was flipped: the pane inside the site's frame in a real browser (the empty state and the theme), and one real upload with the human check, which is the only thing that proves the widget's secret pairs with its site key. Both are the owner's first checks after the deploy (the runbook).
What the App keeps¶
The Cloud Crawler engine (cloud-crawler-core) and the App edition, which runs
on Azure Container Apps beside an Azure MCP Server under a managed identity or
on-behalf-of authentication. The engine is seeded and versioned in the App and
adopted unchanged by the AddOn when the App releases.
What the AddOn is¶
The lab edition. It collects evidence but never fetches it: a visitor
uploads an Azure Resource Graph export (a Terraform state or plan is
accepted too, but the engine this version runs does not read it); it validates,
hashes, redacts and normalises it, runs
deterministic drift detectors against the decision records in the session, and
answers with evidence, drift findings, draft decision records and review
proposals. Everything lives in memory and expires after two hours. It is
technically unable to reach Azure: no cloud SDK is installed, it refuses to
start if azure, msal or boto3 can be imported or if any Azure identity
variable is set, and its health answer reports azureConnectivity:
"disabled-by-design". Its README also describes a lab chat path in which the
site hands it evidence it obtained on the visitor's behalf; that path is
planned, not built, and would be reached by the site's Function App over https
exactly as /api/health is.
How the row was flipped¶
The migration and cloud assessment rows flipped in one pull request
(migration, cloud assessment). Here it
took two, so that the public catalogue never said available before the
container ran (owner decision of 2026-10-26, written on
#1357 when
the first pull request was opened).
First pull request,
#1411 (the host
side; the row stayed coming):
- a
group_vars/all.ymlrow with the image digest, the loopback port 18084, theCC_environment and the attestation identity; vault_addon_cloud_crawler_turnstile_secretin the vault-key table (lab-host/README.md) and the runbook's list of keys set by hand (the count of keys is stated in both and changed);ADDON_CLOUD_CRAWLER_URLininfra/functionapp.tf, declared inscripts/assert-expected-plan.mjsas exactly one added app setting;- the owner's steps after the merge: the HCP Terraform run, the playbook run on the host and the status check (the runbook).
Second pull request (after the status route answered configured: true,
reachable: true):
- the row's
statusset toavailable(comingSinceandcomingReasonremoved),capabilitiesset to what the pane uses (downloadsandclipboard-write) and the summary andtechnologyworded for what the lab does today (above); - the origin in
frame-srcand in the three delegations ofPermissions-Policy(frontend/staticwebapp.config.json), with the tests that list the available origins (catalogue.test.js,csp.test.js) and every count of available rows moved from three to four; - in the AddOn's repository,
docs/website-integration/integration-guide.md("Where it stands", the Image row, the loopback port and the pasted row), whose pasted row and loopback port the weekly drift check holds equal to the site's (the runbook); - what the review of the first pull request asked for: a test title and the
API surface note that still said the setting was not provisioned; the
scripts (operations)path filter in.github/workflows/ci.yml(the list of changed files that makes that CI job run), which now includes the registry file thatassert-expected-plan.test.mjsreads; and the plan check's entry forADDON_CLOUD_CRAWLER_URL, deleted now that the setting is applied, as its own comment said to do.
lab-host/ is not touched by the second pull request on purpose: the site
counts every commit under lab-host/ that merges after the host's last
playbook run as "the host is behind" (functions/src/lib/labs/drift.js), so a
wording change there would ask the owner for a playbook run that changes
nothing.