Mock ESP32 ROM bootloader (SLIP) for CI and local upload testing without hardware
Project description
esp32-mock-bootloader
A mock Espressif ROM bootloader for testing firmware uploads without a board.
Run it on your machine or in CI. Point esptool, arduino-cli, or any ROM-compatible flasher at a TCP port or serial path, and flash as if a chip were connected.
Stability: version
0.xis alpha. CLI flags and protocol details may change before1.0.0.
Table of contents
- Overview
- Features
- Requirements
- Installation
- Quick start
- Usage
- Transports
- GitHub Actions
- Protocol references
- Limitations
- Development
- Project layout
- AI disclosure
- License
Overview
Real Espressif chips expose a ROM bootloader over serial. Upload tools speak a SLIP-framed binary protocol: sync, detect the SoC, write flash blocks, verify MD5, and so on.
esp32-mock-bootloader implements enough of that protocol for upload clients to complete a full flash cycle. It does not run your firmware or emulate peripherals — it only answers the bootloader conversation.
esptool / arduino-cli / …
│
▼
socket://127.0.0.1:PORT or /dev/tty* / COM*
│
▼
esp32-mock-bootloader (SLIP server)
│
▼
ACK + chip metadata + in-memory flash image
Chip metadata comes from the installed esptool package. When Espressif adds a new SoC to esptool, this mock can support it without a code change here.
For protocol details and authoritative behavior, see Protocol references.
Features
- No hardware — run upload tests locally and in CI.
- All esptool SoCs — profiles are built from
esptool.targets.CHIP_DEFS. - Auto chip detection —
--chip autolearns the SoC from client traffic. - TCP daemon — background
start/stopwith stablesocket://URLs. - PTY and COM paths — Unix PTY, Windows com0com pairs, or socket fallback.
- GitHub Action — one step to start the mock; teardown runs automatically.
- CI-ready — tested on Ubuntu, Windows, and macOS with esptool integration tests.
Requirements
| Component | Version |
|---|---|
| Python | 3.9 or newer |
| esptool | Installed automatically with this package (runtime dependency) |
| Upload client | e.g. pip esptool, or arduino-cli with a client that supports your transport |
Optional:
- com0com on Windows — for real
COMxports in local testing (setup guide).
Installation
From PyPI:
pip install esp32-mock-bootloader
Pin a release:
pip install esp32-mock-bootloader==0.1.0
From source (development):
git clone https://github.com/lucasssvaz/esp32-mock-bootloader.git
cd esp32-mock-bootloader
pip install -e ".[dev]"
Quick start
# 1. Start the mock (background daemon on port 9876)
esp32-mock-bootloader start
# 2. Flash through it
esptool --chip esp32 \
--port "$(esp32-mock-bootloader url)" \
write-flash 0x10000 firmware.bin
# 3. Stop when done
esp32-mock-bootloader stop
The daemon keeps running between steps 1 and 3. Use status to inspect it, url for the full socket:// address, or port for the port number alone.
Usage
CLI commands
| Command | Description |
|---|---|
start |
Start the background daemon and exit once the port is ready |
stop |
Stops the only running instance by default; --port PORT for one; --port all for every instance |
status |
Auto-picks the only running instance; lists all when several are running; --port PORT or --port all |
url |
Prints one socket:// URL (auto-pick); tab-separated list when several; --port PORT or --port all |
port |
Prints one TCP port (auto-pick); one per line when several; --port PORT or --port all |
erase-flash |
Erases the only running instance by default; --port PORT or --port all |
chips |
List SoCs supported by the installed esptool |
run |
Run the server in the foreground (used internally; prefer start) |
Common flags for start and run:
| Flag | Default | Description |
|---|---|---|
--chip |
auto |
Chip profile, or auto to detect from client traffic |
--port |
9876 |
TCP listen port (run / start); with run --pty in null-modem mode, the upload client serial port (e.g. COM19) — same port you pass to esptool. Falls back to OS-assigned port if taken. |
--serial-bind |
— | run --pty only: mock-side port in a null-modem pair; auto-detected from com0com when only --port is set |
--pty |
off | run only: serial path mode (Unix PTY, null-modem COM, or Windows socket fallback) |
--bind |
127.0.0.1 |
Bind address |
--startup-timeout |
30 |
Seconds start waits for the port (start only) |
--force |
off | Stop an existing daemon on the same port first (start only) |
--exit-on-disconnect |
off | Exit after the first client disconnects on any transport (run; test TCP helpers enable this) |
--timeout |
none | Exit after N seconds (run only) |
status --json adds machine-readable output. With several running instances (or --port all), JSON is {"instances": [...]}; otherwise a single status object.
status, url, port, erase-flash, and stop share --port semantics: omit it to auto-pick (one instance behaves like before; several are listed or all stopped/erased), pass a number for one instance, or pass all to always target every running instance.
When no daemon is running and you omit --port, query commands fall back to port 9876 (the start default) so $(esp32-mock-bootloader url) keeps working in single-daemon CI scripts.
Daemon lifecycle
Runtime files live under the OS temp directory ($TMPDIR/esp32-mock-bootloader/ on macOS/Linux, %TEMP%\esp32-mock-bootloader\ on Windows). A single registry.json tracks every running daemon and foreground run process:
{
"version": 1,
"instances": {
"9876": {
"pid": 12345,
"port": 9876,
"chip": "esp32",
"bind": "127.0.0.1",
"url": "socket://127.0.0.1:9876",
"log_file": "/tmp/esp32-mock-bootloader/port-9876.log",
"detected_chip": "esp32",
"mode": "daemon"
}
}
}
Per-port logs are written alongside the registry. Stale entries are pruned automatically when a process is no longer running. detected_chip is filled after a client identifies the SoC (in auto mode).
Chip selection
esptool’s --chip flag is client-side only — it is never sent over the serial link. The mock cannot read it. Choose the mock profile to match how your upload client selects the SoC:
Mock --chip |
Client | Connect fidelity |
|---|---|---|
esp32, esp32c3, … |
esptool --chip <same> |
Full ROM profile (MAC, crystal, security-info) — recommended for CI |
esp32, esp32c3, … |
esptool --chip auto |
esptool autodetects from ROM probes against the fixed mock profile |
auto |
esptool --chip auto |
Mock learns the SoC from esptool’s standard detection probes |
auto |
esptool --chip <explicit> |
Upload usually works; connect may warn until chip-specific registers are read |
Recommended CI pattern — one virtual board per job, matching chips:
esp32-mock-bootloader start --chip esp32c3
esptool --chip esp32c3 --port "$(esp32-mock-bootloader url)" flash-id
Or let esptool autodetect against a fixed mock profile:
esp32-mock-bootloader start --chip esp32c3
esptool --chip auto --port "$(esp32-mock-bootloader url)" flash-id
Use mock --chip auto when the client also uses --chip auto, or when you need the mock to learn the SoC from chip-specific register traffic (for example multi-SoC protocol tests).
In auto mode the mock:
- Returns a ROM-style error on
GET_SECURITY_INFOuntil a SoC is known. - Returns
0for the legacy probe at0x40001000until chip-specific registers identify the SoC. - Sets
detected_chipfrom unique detect registers or efuse windows (addresses from esptool ROM classes).
ROM profile: For explicit chip modes (and after auto detection), READ_REG returns a sparse set of register values derived from esptool ROM classes — synthetic MAC, crystal calibration (UART_CLKDIV, ESP32 RTCCALICFG1), and security-off defaults. This is not a full efuse block emulator; see espefuse.
Synthetic MAC
esptool's flash-id prints a MAC decoded from efuse/OTP registers. The mock fills those registers with a synthetic BASE_MAC so the line is non-zero and passes each chip family's read_mac() logic. No particular address is required for protocol correctness.
| Property | Value |
|---|---|
| OUI | 24:0A:C4 (Espressif; not a real burned address on the mock) |
| Host suffix | First 3 bytes of SHA256("<chip>"), e.g. esp32 → e2:95:26 |
| Stability | Same --chip always yields the same MAC across runs |
| Uniqueness | Different SoC names get different suffixes (helps multi-chip CI logs) |
Examples: esp32 → 24:0a:c4:e2:95:26, esp32c3 → 24:0a:c4:1f:67:7d, esp8266 → 24:0a:c4:ce:2b:c1.
To compute the expected MAC in a test: registers.mac_bytes_for_chip("esp32c3") or the formula above. A single fixed MAC for all chips would also work with esptool; the per-chip suffix is a readability choice, not a hardware requirement.
Supported chips
Every target in the installed esptool CHIP_DEFS is available:
esp32-mock-bootloader chips
esp32-mock-bootloader chips --json # detect registers and chip_id metadata
New esptool releases can add SoCs without updating this package.
Transports
TCP (default)
The daemon listens on 127.0.0.1:PORT. Pip-installed esptool accepts socket:// URLs via pyserial.
esp32-mock-bootloader start --port 9876
esptool --chip esp32c6 --port socket://127.0.0.1:9876 write-flash 0x10000 app.bin
VID/PID messages
esptool reads USB vendor/product IDs only from real USB serial devices (Espressif VID 0x303A). Virtual transports cannot provide those descriptors:
| Transport | Typical esptool message | Fixable by mock? |
|---|---|---|
socket:// |
Device VID/PID identification is only supported on COM and /dev/ serial ports. |
No — document only |
Unix PTY (/dev/ttys…) |
Failed to get VID/PID of a device on /dev/ttys… |
No — PTY is not a USB device |
Windows com0com (COMx) |
Same Failed to get VID/PID — virtual pairs have no USB descriptors |
No |
These messages are harmless for upload tests. Only a physical Espressif USB-Serial/JTAG adapter silences them.
PTY / serial path
Use --pty with run when a tool expects a device path instead of a URL (common with arduino-cli):
esp32-mock-bootloader run --pty --chip esp32
# The PTY path is printed to stdout; use --port-file to write it to a file:
esp32-mock-bootloader run --pty --port-file /tmp/mock-pty --chip esp32
esptool --chip esp32 --port "$(cat /tmp/mock-pty)" write-flash 0x10000 firmware.bin
| Platform | --pty provides |
|---|---|
| Linux / macOS | Real PTY device (e.g. /dev/ttys003) |
| Windows (local) | com0com virtual COM pair |
| Windows (CI) | socket://127.0.0.1:PORT fallback when no COM pair is configured |
PTY vs COM
Both modes expose a serial device path to the client, but they create that path differently:
| PTY (Unix default) | Null-modem serial (--port / --serial-bind) |
|
|---|---|---|
| What it is | Kernel pseudo-terminal pair created by the mock | Two ends of an existing serial device (virtual or physical) |
| Server I/O | Master side of the PTY (PtyMasterTransport) |
pyserial on --serial-bind |
| Client path | Slave device (e.g. /dev/ttys003) |
--port (e.g. COM19); written to --port-file |
| Typical platform | Linux / macOS | Windows (com0com); Linux with socat loopback |
| Needs extra software | No | Yes on Windows (com0com); paired ports on Linux |
Null-modem mode is not Windows-only. Any path pyserial can open works on any OS. Unix CI defaults to PTY because the kernel provides a free pair with no setup.
On Windows with com0com you usually pass only --port COM19 (the upload port). The mock looks up the paired port via setupc and binds there automatically. Pass --serial-bind COM18 as well when you want to name both ends explicitly.
Legacy env vars ESP32_MOCK_COM_PORT / ESP32_MOCK_COM_PEER still work; prefer ESP32_MOCK_SERIAL_BIND and ESP32_MOCK_PORT.
Windows with com0com
Install com0com. The mock binds the paired port; --port is what esptool uses (written to the path file):
esp32-mock-bootloader run --pty --port-file mock.port ^
--port COM19 --chip esp32
esptool --chip esp32 --port COM19 write-flash 0x10000 firmware.bin
To name both ends explicitly:
esp32-mock-bootloader run --pty --port-file mock.port ^
--serial-bind COM18 --port COM19 --chip esp32
Expect Failed to get VID/PID on com0com ports (see VID/PID messages).
Environment variables ESP32_MOCK_SERIAL_BIND and ESP32_MOCK_PORT work the same as --serial-bind / --port. Legacy ESP32_MOCK_COM_PORT / ESP32_MOCK_COM_PEER are still read.
Helper script (elevated prompt; creates a pair, runs esptool, removes the pair):
python scripts\test_windows_com.py
Set ESP32_MOCK_KEEP_COM_PAIR=1 to leave the pair installed after the script exits.
GitHub Actions
The action starts the daemon in the main step and stops it in a post step when the job ends — including on failure. No manual stop required.
jobs:
upload-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Mock bootloader
uses: lucasssvaz/esp32-mock-bootloader@v0.1.0
id: mock
- name: Flash test firmware
run: |
pip install esptool
esptool --chip esp32 \
--port "${{ steps.mock.outputs.url }}" \
--no-stub --before no-reset --after no-reset \
write-flash 0x10000 firmware.bin
Outputs: url (socket://…), port.
Inputs (all optional):
| Input | Default | Description |
|---|---|---|
chip |
auto |
Chip profile |
port |
9876 |
TCP port |
startup-timeout |
30 |
Startup wait in seconds |
python-version |
3.x |
Python for setup-python |
version |
(empty) | PyPI pin (e.g. 0.1.0); omit to install from the action checkout |
Manual CLI in a workflow (without the action):
- run: pip install esp32-mock-bootloader esptool
- run: esp32-mock-bootloader start
- run: |
esptool --chip esp32 --port "$(esp32-mock-bootloader url)" \
write-flash 0x10000 firmware.bin
- run: esp32-mock-bootloader stop
if: always()
Client examples
esptool (TCP, no stub — typical for CI):
esptool --chip esp32c6 \
--port socket://127.0.0.1:9876 \
--no-stub --before no-reset --after no-reset \
write-flash 0x10000 app.bin
arduino-cli:
arduino-cli compile -b esp32:esp32:esp32 \
-p socket://127.0.0.1:9876 --upload sketch.ino
Shell CI script:
esp32-mock-bootloader start
PORT="$(esp32-mock-bootloader url)"
# run your upload tests against "$PORT"
esp32-mock-bootloader stop
Python API
The public surface is intentionally small: start a mock, read its endpoint, optionally query or stop running instances. Upload clients (esptool, arduino-cli) connect to handle.url() — the mock never runs uploads for you.
Exports: mock_bootloader, MockHandle, instances, __version__
Style A — context manager (single instance, auto cleanup)
import subprocess
from esp32_mock_bootloader import mock_bootloader
with mock_bootloader(chip="esp32") as mock:
subprocess.run(["esptool", "--chip", "esp32", "--port", mock.url(), "write-flash", ...])
Style B — imperative (multiple instances)
from esp32_mock_bootloader import mock_bootloader
server_a = mock_bootloader(chip="esp32")
server_b = mock_bootloader(chip="esp32c3")
try:
# point esptool / arduino-cli at server_a.url() and server_b.url()
...
finally:
server_b.stop()
server_a.stop()
instances — CLI-parity operations
Same verbs as esp32-mock-bootloader status|url|port|stop|erase-flash:
from esp32_mock_bootloader import mock_bootloader, instances
server_a = mock_bootloader(chip="esp32")
server_b = mock_bootloader(chip="esp32c3")
print(instances.status(format="text")) # table of all running mocks
rows = instances.status() # list[dict] when multiple
urls = instances.url(port="all")
instances.erase_flash(port=server_a.port())
instances.stop(port="all")
Each MockHandle exposes the same verbs scoped to that server: server_a.url(), server_a.status(), server_a.erase_flash(), server_a.stop(), etc.
Default mode for mock_bootloader() is foreground (subprocess server; stops when the handle is destroyed or the with block ends). Use mode="daemon" for a background daemon like esp32-mock-bootloader start.
Advanced (opt-in)
Protocol testing and raw transports live under esp32_mock_bootloader.advanced:
from esp32_mock_bootloader import mock_bootloader
from esp32_mock_bootloader.advanced import protocol
server = mock_bootloader(chip="esp32")
try:
client = protocol.connect(server)
client.send_command(cmd, data)
finally:
server.stop()
Also exported: transport, process, protocol_client, constants. Chip metadata: from esp32_mock_bootloader import chips.
Runnable scripts with comments live under examples/ (basic upload patterns and esp32_mock_bootloader.advanced protocol examples).
Reference constants (FLASH_APP_OFFSET, SYNC_PAYLOAD, …) live in esp32_mock_bootloader.constants.
How it works
The mock speaks SLIP-framed ROM commands. Implemented handlers include:
SYNC, FLASH_BEGIN / DATA / END, FLASH_DEFL_*, MEM_* (+ OHAI after MEM_END), READ_REG, WRITE_REG (with mask, readable via READ_REG), GET_SECURITY_INFO, SPI_SET_PARAMS, SPI_ATTACH, CHANGE_BAUDRATE, SPI_FLASH_MD5, READ_FLASH_SLOW (ROM), and stub-only ERASE_FLASH, ERASE_REGION, READ_FLASH (streaming + MD5), RUN_USER_CODE. FLASH_DATA, MEM_DATA, and FLASH_DEFL_DATA validate the 0xEF XOR checksum (ROM error 0x07, stub error 0xC1). Unknown commands return ROM error 0x05 or stub error 0xFF.
Flash data is stored in an in-memory image (erased bytes default to 0xFF). After a stub upload (MEM_END with entrypoint + OHAI), SPI_FLASH_MD5 returns a 16-byte binary digest; in ROM mode it returns 32-byte lowercase hex ASCII — matching esptool’s flash_md5sum() expectations. Unknown commands receive a generic ACK.
The mock validates protocol behavior, not silicon accuracy. It does not model Wi-Fi, sleep, brownout, or real flash timing.
Protocol references
Implementation follows Espressif’s published bootloader protocol and the esptool reference client. Primary sources:
| Topic | Reference |
|---|---|
| Serial protocol overview | esptool serial protocol (ESP32) — same command set is documented per chip under esptool/en/latest/<chip>/advanced-topics/serial-protocol.html |
| Flash upload & MD5 verify | Verifying uploaded data — ROM returns 32 hex ASCII bytes; stub returns 16 raw MD5 bytes before the 2 status bytes |
SPI_FLASH_MD5 (0x13) |
Commands table |
Stub upload & OHAI |
Functional description — initialization — MEM_END entrypoint, unsolicited OHAI SLIP packet |
| Client MD5 handling | esptool loader.py — flash_md5sum — RESP_DATA_LEN 32 (ROM) vs RESP_DATA_LEN_STUB 16 (stub); status bytes follow the digest |
| Stub lifecycle | esptool loader.py — run_stub — RAM download via MEM_*, then mem_finish(entry) |
| Chip profiles & detection | esptool targets / CHIP_DEFS — register addresses, magic values, security info |
Integration tests in downstream projects (e.g. arduino-esp32 upload tests) exercise the default stub path (flasher.py / esptool without --no-stub). CI examples in this repo that pass --no-stub target the ROM MD5 format explicitly.
Limitations
- Protocol emulator only — no application code runs on the mock.
- Client packaging matters — some bundled esptool builds lack
socket://; use PTY/COM or pip esptool. - com0com is local — GitHub-hosted Windows runners use the socket fallback automatically.
- VID/PID noise on virtual ports — socket, PTY, and com0com cannot expose Espressif USB descriptors; esptool prints informational VID/PID messages (see Transports).
- Alpha API — expect changes before
1.0.0.
espefuse
This mock targets esptool ROM upload clients (write-flash, flash-id, stub upload). It is not an efuse programmer.
| Tool / mode | Use with mock? |
|---|---|
espefuse --virt |
Yes — in-process efuse emulation for host-side tests (no serial port) |
espefuse --port … read/burn commands |
No — requires on-chip efuse controller WRITE_REG sequences and persistent burned state |
After connect, the mock exposes a sparse ROM profile (MAC, crystal registers, security-off defaults) so esptool connect paths behave plausibly. That is not espefuse field parity:
| espefuse command | Mock support |
|---|---|
summary |
Partial / best-effort only — most named fields stay at defaults |
dump, adc-info, check-error |
No — unmapped addresses read as 0 |
burn-*, read-protect-efuse, write-protect-efuse |
No — permanently out of scope unless a full efuse controller emulator is added |
Supported chips follow installed esptool CHIP_DEFS. espefuse supported chips are a subset (no ESP8266).
Development
See CONTRIBUTING.md for pull request guidelines and AI disclosure expectations.
git clone https://github.com/lucasssvaz/esp32-mock-bootloader.git
cd esp32-mock-bootloader
pip install -e ".[dev]"
Run tests:
pytest # parallel by default (pytest-xdist)
pytest -n0 # single process (debugging)
pytest -m "not esptool" # protocol unit tests only
pytest -m "not transport" # skip TCP/PTY integration
pytest tests/test_protocol.py -m transport # TCP transport smoke only
pytest tests/test_process.py # process.py + transport.py (advanced)
pytest tests/test_com0com.py # com0com unit tests
CI runs the full suite on Ubuntu, Windows, and macOS (parallel via pytest-xdist), enforces coverage baselines on Ubuntu, and verifies parallel subprocess coverage with scripts/verify_parallel_coverage.py.
com0com testing tiers:
- CI (all OS) —
tests/test_com0com.pyusestests/fixtures/fake_setupc.py(no driver install). - Windows CI —
test_windows_com0com_esptoolskips when setupc is missing or not elevated. - Local Windows — install com0com, run elevated:
pytest -m com0comorscripts/test_windows_com.py.
pytest -m com0com # optional real com0com integration (Windows + admin)
Coverage (parallel + subprocess children; see reports/README.md):
pytest -n auto --cov-config=pyproject.toml \
--cov=esp32_mock_bootloader \
--cov-report=term-missing \
--cov-report=html:reports/htmlcov \
--cov-report=xml:reports/coverage.xml
python scripts/verify_parallel_coverage.py
python scripts/check_coverage.py
Build a release wheel:
hatch build
Project layout
esp32-mock-bootloader/
├── CONTRIBUTING.md # PR guidelines and AI policy
├── src/esp32_mock_bootloader/ # Python package (api, CLI, daemon, SLIP server)
│ ├── registry.py # Registry (multi-instance coordination)
│ ├── session.py # Internal Session / SessionGroup lifecycle
│ ├── client.py # Protocol Client (bound to Session)
│ ├── api.py # mock_bootloader() and MockHandle
│ ├── instances.py # CLI-parity status/url/port/stop/erase_flash
│ ├── advanced/ # Opt-in protocol.connect, transport, process, constants
│ ├── constants.py # Protocol/layout reference values
│ ├── transport.py # TCP / PTY / serial client connections
│ ├── process.py # Subprocess spawn and teardown helpers
│ ├── protocol_client.py # SLIP client helpers
│ ├── chips.py # Chip profiles from esptool
│ ├── registers.py # Sparse ROM register profile for esptool fidelity
│ ├── protocol.py # Protocol constants
│ └── server.py # SLIP server (advanced)
├── examples/ # Runnable basic + advanced usage examples
├── action/ # Node.js steps for the GitHub Action
├── action.yml # Composite action entry point
├── tests/ # pytest suite (protocol, esptool, transports)
├── scripts/ # Coverage checker, Windows COM helper
├── reports/ # Coverage config and baselines
└── .github/workflows/ # CI and release pipelines
AI disclosure
This repository was developed with help from AI coding assistants. Every change is reviewed and tested by a human maintainer before merge or release.
Contributor expectations (disclosure, review, commit trailers) are in CONTRIBUTING.md.
License
Copyright 2026 Lucas Saavedra Vaz. Released under the Apache-2.0 license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file esp32_mock_bootloader-0.3.0.tar.gz.
File metadata
- Download URL: esp32_mock_bootloader-0.3.0.tar.gz
- Upload date:
- Size: 55.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdc343366fb2fe8173423efea53176e3d4868146730b8ada7a28c78837ad82df
|
|
| MD5 |
d106d0e8ada73df3ee0ce2a2764b997d
|
|
| BLAKE2b-256 |
fcd92a9b1c4976c44a85b46ccdd25adf0d3693b9310f532d26d6df338d8ab6aa
|
Provenance
The following attestation bundles were made for esp32_mock_bootloader-0.3.0.tar.gz:
Publisher:
release.yml on lucasssvaz/esp32-mock-bootloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
esp32_mock_bootloader-0.3.0.tar.gz -
Subject digest:
bdc343366fb2fe8173423efea53176e3d4868146730b8ada7a28c78837ad82df - Sigstore transparency entry: 1855833544
- Sigstore integration time:
-
Permalink:
lucasssvaz/esp32-mock-bootloader@1c0d9bb54418c7983f9d6e0526b49ba003df3e27 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/lucasssvaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1c0d9bb54418c7983f9d6e0526b49ba003df3e27 -
Trigger Event:
push
-
Statement type:
File details
Details for the file esp32_mock_bootloader-0.3.0-py3-none-any.whl.
File metadata
- Download URL: esp32_mock_bootloader-0.3.0-py3-none-any.whl
- Upload date:
- Size: 57.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
856e01bbc0c3ecd009cb08bb1ef5b19e6f656e3eede82f320dcc120600822270
|
|
| MD5 |
66e8cd67f05fcc4ac39b3ba7f73c3efe
|
|
| BLAKE2b-256 |
29ad28c90308842445fd209297a91dbd8aa3027ec52e541710ec30a5ed5234da
|
Provenance
The following attestation bundles were made for esp32_mock_bootloader-0.3.0-py3-none-any.whl:
Publisher:
release.yml on lucasssvaz/esp32-mock-bootloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
esp32_mock_bootloader-0.3.0-py3-none-any.whl -
Subject digest:
856e01bbc0c3ecd009cb08bb1ef5b19e6f656e3eede82f320dcc120600822270 - Sigstore transparency entry: 1855833613
- Sigstore integration time:
-
Permalink:
lucasssvaz/esp32-mock-bootloader@1c0d9bb54418c7983f9d6e0526b49ba003df3e27 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/lucasssvaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1c0d9bb54418c7983f9d6e0526b49ba003df3e27 -
Trigger Event:
push
-
Statement type: