Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 7 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,28 +88,13 @@ jobs:
run: |
docker save iolinki-zephyr-base > zephyr-base-image.tar

# The following jobs exist to satisfy branch protection requirements. They
# depend only on the lightweight host gate, NOT on the heavy Zephyr job.
quality-gate:
needs: docker-validation
sbom-tools:
runs-on: ubuntu-latest
steps:
- run: echo "Quality Gate passed (verified in docker-validation)"

build-and-test:
needs: docker-validation
runs-on: ubuntu-latest
steps:
- run: echo "Build and Test passed (verified in docker-validation)"

build-bare-metal:
needs: docker-validation
runs-on: ubuntu-latest
steps:
- run: echo "Bare Metal build passed (verified in docker-validation)"
- uses: actions/checkout@v4
- name: Test SBOM generator
run: python3 tools/test_generate_sbom.py

build-example:
needs: docker-validation
runs-on: ubuntu-latest
steps:
- run: echo "Zephyr Example build passed (verified in docker-validation)"
# Branch protection on develop requires the REAL jobs directly:
# docker-validation, zephyr-validation, sbom-tools. Do not reintroduce
# echo-only proxy jobs — they let a red job hide behind a green run.
16 changes: 16 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ jobs:
# Cat to console for debugging
cat release_notes.md

- name: Generate SBOMs
run: |
# Reproducible timestamps: pin to the release commit time
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
python3 tools/test_generate_sbom.py
python3 tools/generate_sbom.py \
--version "${{ steps.version.outputs.version }}" \
--format cyclonedx \
--output "iolinki-${{ steps.version.outputs.version }}.cdx.json"
python3 tools/generate_sbom.py \
--version "${{ steps.version.outputs.version }}" \
--format spdx \
--output "iolinki-${{ steps.version.outputs.version }}.spdx.json"

- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
Expand All @@ -98,6 +112,8 @@ jobs:
files: |
build/examples/simple_device/simple_device
build/tests/test_init
iolinki-${{ steps.version.outputs.version }}.cdx.json
iolinki-${{ steps.version.outputs.version }}.spdx.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ All notable changes to the `iolinki` project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - 2026-07-02
### Added
- **Per-release SBOMs**: every tagged release now ships CycloneDX 1.6 and SPDX 2.3
SBOMs (`iolinki-<version>.cdx.json` / `.spdx.json`) generated by
`tools/generate_sbom.py` and attached as release assets.
- **Security documentation package**: CRA-ready coordinated-disclosure policy
(`SECURITY.md`), STRIDE threat model aligned to IO-Link Security Design and
Development Guideline 10.512 (`docs/security/THREAT_MODEL.md`), and a Cyber
Resilience Act overview for device makers (`docs/security/CRA.md`).

### Fixed
- **Zephyr module build**: `zephyr/CMakeLists.txt` still referenced
`src/iolink_core.c`, deleted by the singleton-API removal; the module now
builds against `src/device.c`. The breakage was invisible because
`zephyr-validation` was not a required check.

### Changed
- **CI gates are now real**: branch protection on `develop` and `main` requires
`docker-validation`, `zephyr-validation`, and `sbom-tools` directly; the
echo-only proxy jobs (`quality-gate`, `build-and-test`, `build-bare-metal`,
`build-example`) are removed.

## [1.1.2] - 2026-06-15
### Fixed
- **Device communication over the UART PHY**: the DLL booted in SIO mode and only left it upon electrical wake-up detection. A plain UART PHY cannot observe the C/Q wake-up pulse (`detect_wakeup == NULL`), so a device on real UART hardware stayed in SIO forever and never serviced M-sequences. The DLL now starts in SDCI when the PHY cannot detect wake-up (the already-established-COM contract of the UART PHY), so the device responds to the Master immediately.
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,17 @@ See [ROADMAP.md](./docs/ROADMAP.md) for detailed development phases.
- **[INSTALL.md](./INSTALL.md)** - Detailed installation instructions
- **[PUPPETEER.md](./docs/PUPPETEER.md)** - Agent task mutex workflow (submodule)

## Security

- **[SECURITY.md](./SECURITY.md)** — coordinated disclosure policy and CRA-ready
vulnerability handling
- **[Threat model](./docs/security/THREAT_MODEL.md)** — STRIDE analysis aligned to
the IO-Link Security Design and Development Guideline (Order No. 10.512), every
claim anchored to code and tests
- **[CRA overview](./docs/security/CRA.md)** — what the EU Cyber Resilience Act
means for devices built on this stack; free vs. commercial deliverables
- **SBOMs** — CycloneDX 1.6 + SPDX 2.3 attached to every tagged release

## Releases

Official releases are available on [GitHub Releases](https://github.com/yourusername/iolinki/releases).
Expand Down
68 changes: 58 additions & 10 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,69 @@
# Security Policy

`iolinki` is a dual-licensed IO-Link device stack intended for integration into
industrial products. Security is handled as an engineering discipline here, not a
checkbox: the stack ships with a public [threat model](docs/security/THREAT_MODEL.md)
aligned to the IO-Link Security Design and Development Guideline (Order No. 10.512),
per-release SBOMs, and the coordinated-disclosure process below. See
[docs/security/CRA.md](docs/security/CRA.md) for what this means for your product
under the EU Cyber Resilience Act.

## Supported Versions

Only the latest `main` branch and the latest tagged release are supported with security updates.
| Version | Security fixes |
| ------- | -------------- |
| Latest tagged release + `develop` | ✅ free of charge |
| Older releases | Under a commercial support agreement only |

| Version | Supported |
| ------- | ------------------ |
| Latest | :white_check_mark: |
| < 0.1.0 | :x: |
Security fixes are delivered as tagged releases with a changelog entry and, for
confirmed vulnerabilities, a GitHub security advisory. Commercial licensees can
contractually fix a support period per release (default five years) — see the
commercial security-update terms.

## Reporting a Vulnerability

If you discover a security vulnerability in `iolinki`, please do NOT open a public issue.
Please do **not** open a public issue for suspected vulnerabilities.

1. **Preferred:** GitHub private vulnerability reporting — use *Report a
vulnerability* under the repository's **Security** tab.
2. Alternatively, contact the maintainer privately (contact details on the GitHub
profile).

What to include: affected version/commit, the IO-Link frame or ISDU sequence (or
code path) that triggers the issue, and impact as you understand it. A proof of
concept against the virtual PHY or the docker test harness is ideal but not
required.

**Response targets:**

- Acknowledgement within **72 hours**.
- Triage verdict (accepted / rejected / needs info) within **14 days**.
- Fix timeline agreed with the reporter at triage; critical issues in the frame or
ISDU parsing paths are prioritized ahead of all other work.

## Coordinated Disclosure

We ask reporters to withhold public disclosure until a fixed release is available.
In return we commit to: keeping the reporter informed, crediting them in the
advisory and changelog (unless they prefer otherwise), and not taking legal action
against good-faith research performed against your own or simulated hardware.

## CRA Readiness

Instead, please report it via:
For products placed on the EU market, Regulation (EU) 2024/2847 (Cyber Resilience
Act) applies — its vulnerability-reporting obligations from September 2026, its
full obligations from December 2027. As the supplier of a commercially licensed
stack we maintain the corresponding internal process: confirmed actively exploited
vulnerabilities in the stack are handled under the CRA notification regime (early
warning within 24 hours, notification within 72 hours) and communicated to
commercial licensees so they can meet their own Article 14 duties.

1. **GitHub Private Reporting**: Use the "Report a vulnerability" button in the `Security` tab if enabled.
2. **Email**: Contact the maintainers directly (details in `AUTHORS` or via GitHub profile).
Machine-readable SBOMs (CycloneDX 1.6 and SPDX 2.3) are attached to every tagged
release. The stack has **zero third-party runtime dependencies**; the SBOM states
this explicitly rather than by omission.

We will investigate all reports and provide a fix as soon as possible.
Integrating the stack does not transfer manufacturer obligations: device makers
remain responsible for their own conformity assessment, CE marking, and reporting.
The commercial CRA package (compliance statement mapped to your product context,
contractual update terms) exists to feed your technical documentation — see
[docs/security/CRA.md](docs/security/CRA.md).
57 changes: 57 additions & 0 deletions docs/security/CRA.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# iolinki and the EU Cyber Resilience Act

*This page is orientation for device makers evaluating the stack. It is not legal
advice; your conformity assessment is yours.*

## You remain the manufacturer

Integrating `iolinki` — or any third-party stack — does not change your status
under Regulation (EU) 2024/2847 (the Cyber Resilience Act). CE marking, the EU
Declaration of Conformity, the ten-year technical-documentation retention, and the
Article 14 reporting obligations for your product stay entirely with you. What a
stack supplier owes you is the *foundation* your technical documentation builds
on. That is exactly what this package is.

Key dates: the CRA's vulnerability-reporting obligations apply from
**11 September 2026**; the full obligations from **11 December 2027**.

## What iolinki provides

| Deliverable | Where | Terms |
|---|---|---|
| SBOM per release (CycloneDX 1.6 + SPDX 2.3) | attached to every [tagged release](https://github.com/w1ne/iolinki/releases) | free, public |
| STRIDE threat model aligned to IO-Link guideline 10.512 | [`docs/security/THREAT_MODEL.md`](THREAT_MODEL.md) | free, public |
| Coordinated disclosure + advisory process | [`SECURITY.md`](../../SECURITY.md) | free, public |
| CRA compliance statement mapping the stack to Regulation (EU) 2024/2847 Annex I, issued per stack release for your product context | commercial license package | commercial |
| Contractually agreed security updates over a defined support period (default five years) | commercial license package | commercial |

The public artifacts let you verify our engineering rigor before you talk to us.
The commercial artifacts are the contract-grade documents your CRA technical file
and your supplier-management process need — the same package other stack vendors
have announced for late 2026, available from us now (pending final legal review of
the statement wording).

## Why a protocol stack is in scope at all

Commercially licensed software placed on the EU market is a "product with digital
elements" under the CRA. As the stack's supplier we carry manufacturer obligations
for the stack itself — which is why the SBOM, the disclosure process, and the
support-period commitment exist as maintained artifacts rather than sales
material. The stack is in the CRA's *default* (non-critical) class: conformity is
self-assessed, no notified body involved.

## The division of labor, concretely

**We cover (for the stack):** risk analysis of the stack's attack surface
(threat model), input-validation and integrity mechanisms with code anchors,
SBOM, vulnerability handling and advisories, security fixes over the support
period.

**You cover (for your device):** your product risk assessment, firmware update
mechanism and its authenticity verification (the stack does not include the
BLOB Transfer & Firmware Update profile — see the threat model's gaps section),
boot integrity, physical-protection guidance in your user documentation, your
DoC, CE marking, and Article 14 reporting.

For commercial-package inquiries, use the contact on the maintainer's GitHub
profile or open a (non-security) discussion on the repository.
Loading
Loading