Skip to content
Merged
Show file tree
Hide file tree
Changes from 160 commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
1b1b9ba
refactor: reorganize pairing service credentials handling and improve…
simonvanlierde Apr 22, 2026
dc2d31b
feat: add pairing state endpoint and client-side polling for setup page
simonvanlierde Apr 22, 2026
c1fd12d
refactor: improve logging for pairing errors and adjust log levels fo…
simonvanlierde Apr 22, 2026
f52fd64
fix: linting
simonvanlierde Apr 22, 2026
4568c56
refactor: update backend API endpoints
simonvanlierde Apr 29, 2026
10496b9
fix: update docstring
simonvanlierde Apr 29, 2026
d503346
fix: remove unused variable
simonvanlierde Apr 30, 2026
c485070
fix: enhance YouTube embed URL handling and add tests for validation
simonvanlierde Apr 30, 2026
26dc0f1
fix: enhance content security policies and update related tests
simonvanlierde Apr 30, 2026
bf20f02
fix: harden relay websocket client handling
simonvanlierde May 6, 2026
c0b7482
fix(pairing): require auth for local pairing actions
simonvanlierde May 6, 2026
2876428
fix(relay): allowlist backend relay commands
simonvanlierde May 6, 2026
35784fd
fix(config): require secure pairing backend by default
simonvanlierde May 6, 2026
fcf4dcf
ci: add security workflow for container scanning and dependency audits
simonvanlierde May 6, 2026
4d9955e
feat: Enforce S3 and OTLP endpoint transport policy
simonvanlierde May 6, 2026
7230a1a
test: Cover S3 and OTLP transport validation
simonvanlierde May 6, 2026
9dbbef1
docs: Document S3 and OTLP HTTPS requirements
simonvanlierde May 6, 2026
39505cb
feat: Enforce relay TLS policy for persisted and paired credentials
simonvanlierde May 6, 2026
6e486b0
feat: Require same-origin checks for cookie-auth writes
simonvanlierde May 6, 2026
1dbd90e
docs: update docs
simonvanlierde May 6, 2026
c78c1b8
fix: sanitize metadata-derived object key segments
simonvanlierde May 6, 2026
0129b11
fix: clean cached preview thumbnails
simonvanlierde May 6, 2026
e29d083
feat: Harden camera control and capture metadata payloads
simonvanlierde May 6, 2026
0d49bc4
feat: Require auth for preview start and stop routes
simonvanlierde May 6, 2026
ab66cf9
feat: Limit pending relay commands
simonvanlierde May 6, 2026
f251c0c
feat: Bound capture upload retry queue
simonvanlierde May 6, 2026
2ed571f
feat: tighten plugin browser CSP and move page scripts out of templates
simonvanlierde May 6, 2026
07a433f
feat: restrict plugin CORS and private-network access with built-ins
simonvanlierde May 6, 2026
7521dc4
fix: hide setup topology from public visitors
simonvanlierde May 6, 2026
e9d674c
docs: make plugin OpenAPI docs development-only and export schema art…
simonvanlierde May 6, 2026
e879a0b
docs: update docs
simonvanlierde May 6, 2026
cd98220
fix(docker): harden app runtime and remove entrypoint shim
simonvanlierde May 7, 2026
0d965db
chore(docker): pin container inputs by digest and checksum
simonvanlierde May 7, 2026
c306b1a
fix(docker): default media and storage listeners to loopback
simonvanlierde May 7, 2026
3b733cf
ci: require review for sensitive dependency updates
simonvanlierde May 7, 2026
00c3ecb
docs(install): document least-privilege camera deployment
simonvanlierde May 7, 2026
5331bdd
feat: redact logs and keep pairing banners local-only
simonvanlierde May 7, 2026
feca1b5
feat: require auth for metrics scraping
simonvanlierde May 7, 2026
ac2826b
feat: return stable 5xx camera errors
simonvanlierde May 7, 2026
4f488fd
docs: document authenticated observability shipping
simonvanlierde May 7, 2026
e4ded1f
feat: Encode camera IDs in backend and relay URLs
simonvanlierde May 12, 2026
d9de2d1
feat: Validate focus request field consistency
simonvanlierde May 12, 2026
746d507
feat: Tighten shared seam validation
simonvanlierde May 12, 2026
11c62b2
feat: Share relay text frame limit in plugin
simonvanlierde May 12, 2026
ca2837b
feat: only accept python deps older than 3 days to avoid supply chain…
simonvanlierde May 12, 2026
e8e5722
refactor(rpi-cam): centralize relay contract policy
simonvanlierde May 13, 2026
71a930a
fix: tighten settings validation
simonvanlierde May 13, 2026
ea60f30
fix: bound command envelope inputs
simonvanlierde May 13, 2026
d42d6bc
feat: rate limit sensitive device actions
simonvanlierde May 13, 2026
7e8f92d
auth: align browser session cookies with ASVS V3
simonvanlierde May 13, 2026
3ff02c7
security: harden browser headers and CSP nonces
simonvanlierde May 13, 2026
679ff96
security: make local key responses non-cacheable downloads
simonvanlierde May 13, 2026
e03e769
fix: trust only loopback proxy headers
simonvanlierde May 13, 2026
d804c05
refactor: rely on framework response media types
simonvanlierde May 13, 2026
cc8b0e9
feat: centralize pairing code contract
simonvanlierde May 13, 2026
046ea2a
fix(auth): keep pairing actions on protected router
simonvanlierde May 13, 2026
9d7a69d
test(auth): cover authorization route boundaries
simonvanlierde May 13, 2026
37d16e6
security: update generated capture file limits
simonvanlierde May 13, 2026
8ad8cf6
security: validate generated capture files before reuse
simonvanlierde May 13, 2026
98e2399
security: enforce browser session lifetimes
simonvanlierde May 13, 2026
8f26db5
security: expose logout on authenticated setup UI
simonvanlierde May 13, 2026
97a2694
security: add relay signing key validation
simonvanlierde May 13, 2026
a9c3ed7
security: make device assertion JWT signing explicit
simonvanlierde May 13, 2026
5a4576c
security: validate relay assertion credentials at boundaries
simonvanlierde May 13, 2026
ae51c9d
security: name CSPRNG byte sizes for generated secrets
simonvanlierde May 13, 2026
51c0025
feat: reject redirected backend reachability probes
simonvanlierde May 13, 2026
a5815e2
feat: harden backend callback URL handling
simonvanlierde May 13, 2026
32ff831
feat: bound pairing HTTP behavior explicitly
simonvanlierde May 13, 2026
d56cff5
test: assert persisted relay credentials are private
simonvanlierde May 13, 2026
8cf96fd
feat(logging): add structured security event helper and shared cache …
simonvanlierde May 13, 2026
7127516
feat(middleware): validate X-Request-ID and log rate-limit blocks
simonvanlierde May 13, 2026
0eff96b
feat(auth): log auth failures, CSRF rejections, and session lifecycle…
simonvanlierde May 13, 2026
98caaea
feat: add generic unhandled exception handler with client-safe output
simonvanlierde May 13, 2026
d4f0981
feat: log relay command security events (rate limit, malformed, forbi…
simonvanlierde May 13, 2026
ae3adff
feat: log local-client hls access denial events
simonvanlierde May 13, 2026
1b601db
feat: add no-store headers to local-key and local-access endpoints
simonvanlierde May 13, 2026
35e3a6a
feat: reveal local API key on demand instead of embedding in HTML
simonvanlierde May 13, 2026
1f80df5
fix: apply 0600 permissions before atomic credential file rename
simonvanlierde May 13, 2026
03ecdaa
security(config): reject DEBUG=true when APP_ENV=production
simonvanlierde May 13, 2026
0e25434
security: block HTTP TRACE method with 405 on all routes
simonvanlierde May 13, 2026
bed835f
security: restrict static serving to .css, .ico, .js, and .png
simonvanlierde May 13, 2026
c93703d
security: validate request-ID input and add cache-control for dynamic…
simonvanlierde May 13, 2026
4104260
security: bound all outbound HTTP and WebSocket clients with explicit…
simonvanlierde May 13, 2026
020ed4e
security: bound botocore client config and sanitize object key segments
simonvanlierde May 13, 2026
9c08119
feat(security): validate S3 public URL template transport and relay P…
simonvanlierde May 13, 2026
8f2d4b5
test(security): validate relay signing credentials with real key mate…
simonvanlierde May 13, 2026
72bbb7c
refactor: inline capture ID generation, remove crypto_policy indirection
simonvanlierde May 13, 2026
127eec4
feat: add connection pool limits to MediaMTX API httpx client
simonvanlierde May 13, 2026
a4e5560
fix: remove unreachable upload_label default from _post_file
simonvanlierde May 13, 2026
ee37ca6
test: replace fragile sleep with drain-count loop in upload queue test
simonvanlierde May 13, 2026
8d4ce6f
chore: suppress ruff ANN401/PLR2004 in tests; reformat minor whitespace
simonvanlierde May 13, 2026
840e3a0
chore: update openapi spec
simonvanlierde May 13, 2026
c190f42
chore: update lockfile
simonvanlierde May 13, 2026
c5b8e45
docs: update docs
simonvanlierde May 13, 2026
06cea1b
feat: expose relay allowlist policy
simonvanlierde May 14, 2026
783f86b
feat: use shared relay forbidden detail
simonvanlierde May 14, 2026
5748e25
document relay allowlist contract ownership
simonvanlierde May 14, 2026
1788cf4
refactor: clarify bootstrap state ownership
simonvanlierde May 14, 2026
002588d
refactor: remove unused repeat task helper
simonvanlierde May 14, 2026
705c928
docs: document runtime boundary ownership
simonvanlierde May 14, 2026
aecd8cd
feat: Centralize RPi connection mode decisions
simonvanlierde May 14, 2026
60d325b
feat: Use connection mode for setup polling
simonvanlierde May 14, 2026
1f51ea9
feat: Fail closed for production loopback pairing backend
simonvanlierde May 14, 2026
b8dd1ad
feat: centralize logging configuration for services in Docker Compose
simonvanlierde Jun 29, 2026
f9c5574
fix: disable credential persistence for actions checkout in workflows
simonvanlierde Jun 29, 2026
a7d60e0
docs: simplify docs
simonvanlierde Jun 29, 2026
0a4c39b
refactor(camera,media,upload): boundary cleanup and protocol extension
simonvanlierde Jun 30, 2026
cfb4810
ci: tighten workflow permissions and checkout
simonvanlierde Jul 1, 2026
3662348
build(docker): move mediamtx Dockerfile to repo root
simonvanlierde Jul 1, 2026
24fd0b8
refactor(models): simplify image model and openapi export
simonvanlierde Jul 1, 2026
b327e4f
refactor(core): fold client_error_detail into headers module
simonvanlierde Jul 1, 2026
c5e0bf9
refactor(relay): colocate device_jwt and note command allowlist
simonvanlierde Jul 1, 2026
129f1d2
refactor: reorganize sinks/media/system into delivery, streaming, obs…
simonvanlierde Jul 1, 2026
218190b
docs: update paths
simonvanlierde Jul 1, 2026
ebdcf99
chore: upgrade deps
simonvanlierde Jul 1, 2026
1fa4591
docs: update changelog
simonvanlierde Jul 1, 2026
c022c85
chore: bump versions to 0.4.0
simonvanlierde Jul 1, 2026
226b9f2
fix: use first backoff tier on initial upload retry
simonvanlierde Jul 1, 2026
cb998f8
fix: wrap S3 public-URL build in ImageSinkError
simonvanlierde Jul 1, 2026
06c0167
fix: reject oversized preview thumbnail cache before reading into memory
simonvanlierde Jul 1, 2026
e4994cf
fix: allow http pairing backend under APP_ENV=development for consist…
simonvanlierde Jul 1, 2026
5656378
fix: ensure explicit checks for None in EXIF metadata conversion
simonvanlierde Jul 1, 2026
f98a5ce
fix: skip prepending base_url when the URL is protocol-relative (//ho…
simonvanlierde Jul 1, 2026
c567622
fix(auth): compare on .encode() bytes so a non-ASCII API key returns …
simonvanlierde Jul 1, 2026
2680788
refactor(router): alias observability router by its own name
simonvanlierde Jul 1, 2026
1cb5ee7
refactor(runtime): inject RuntimeState instead of reaching for the gl…
simonvanlierde Jul 1, 2026
3fee6ad
fix(bootstrap): avoid startup crash from local-key-only or non-dict c…
simonvanlierde Jul 1, 2026
08614db
fix(logging): redact bearer token in quoted/JSON authorization form
simonvanlierde Jul 1, 2026
b4d8212
fix(telemetry): prime cpu_percent so first read isn't 0.0
simonvanlierde Jul 1, 2026
687e59b
refactor(telemetry): drop redundant OSError subclasses in except
simonvanlierde Jul 1, 2026
1924c3e
fix(auth): block backslash open-redirect and rename key snapshot helper
simonvanlierde Jul 1, 2026
1c35def
fix(pairing): guard non-dict credentials file in save path
simonvanlierde Jul 1, 2026
1f8c1e3
fix(relay): serialize binary frame pairs and guard empty content-type
simonvanlierde Jul 1, 2026
a5200b5
fix(ui): recover preview on fatal HLS error and dedup pairing button …
simonvanlierde Jul 1, 2026
d349e79
refactor(setup): drop unreachable success-path button restore
simonvanlierde Jul 1, 2026
d0ed18e
fix(workers): prevent thermal throttle desync and sleeper loop death
simonvanlierde Jul 1, 2026
f8dc5db
fix(compose): map dma_heap device nodes not the parent directory
simonvanlierde Jul 1, 2026
06160fd
fix(ci): correct stale paths, release tag prefix, and gitleaks version
simonvanlierde Jul 1, 2026
5de0f38
refactor(theme): drop legacy matchMedia addListener shim
simonvanlierde Jul 1, 2026
20d01af
fix(utils): harden capture validation and directory cleanup
simonvanlierde Jul 1, 2026
f12079a
fix(models): serialize capture_time as UTC with Z, require aware date…
simonvanlierde Jul 1, 2026
cedf755
test: fix vacuous/misfiled tests and sanitize stop-stream 500
simonvanlierde Jul 1, 2026
14f3bad
docs(install): add transport security notes for local API usage
simonvanlierde Jul 1, 2026
9e79fdc
fix: add HTTP base URL warnings in production
simonvanlierde Jul 1, 2026
e1f21f8
docs(install): add security notes for relay signing key and pairing o…
simonvanlierde Jul 1, 2026
a525264
fix(tests): use monkeypatching for upload worker attributes in lifesp…
simonvanlierde Jul 1, 2026
41589ab
test: drop duplicate ActiveStreamState.to_view test
simonvanlierde Jul 1, 2026
59e1cdf
test(core): fix mislabeled api-key test and drop pydantic round-trip …
simonvanlierde Jul 1, 2026
9829ba5
test(pairing): drop tautological get_state assertion
simonvanlierde Jul 1, 2026
9d880e6
fix(camera): tear down stream when metadata fetch fails
simonvanlierde Jul 1, 2026
64a9841
refactor(camera): drop unused get_youtube_embed_url helper
simonvanlierde Jul 1, 2026
37da9ea
fix(camera): correct off-by-one in nesting-depth error message
simonvanlierde Jul 1, 2026
d06c3e9
chore: add trailing newline to version.py
simonvanlierde Jul 1, 2026
e3d7499
test: relocate shared fakes to tests/fakes
simonvanlierde Jul 1, 2026
2ed3b79
test: drop redundant and duplicate test cases
simonvanlierde Jul 1, 2026
3b3cd67
chore: slim CI/build config to lean 2026 layout
simonvanlierde Jul 1, 2026
0950f06
chore: remove unused pep621 and pinDigests configurations from renova…
simonvanlierde Jul 1, 2026
6a49316
chore: linting
simonvanlierde Jul 1, 2026
93af002
docs: update changelog
simonvanlierde Jul 1, 2026
e3183c6
Merge origin/main into dev
simonvanlierde Jul 1, 2026
e504e09
fix: address code-scanning findings
simonvanlierde Jul 1, 2026
10006fe
chore: bump trixie sha
simonvanlierde Jul 1, 2026
d13883a
docs: note cross-module/string-annotation usage of false-positive-fla…
simonvanlierde Jul 1, 2026
4c9c866
feat: add gitleaks config and ignore clear test value
simonvanlierde Jul 1, 2026
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
15 changes: 10 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
#
# APP_BUILD_TARGET=runtime-standalone
# COMPOSE_PROFILES=standalone
# APP_ENV=development # permits local RustFS over HTTP
#
# IMAGE_SINK=s3
# S3_ENDPOINT_URL=http://host.docker.internal:9000
# S3_ENDPOINT_URL=http://127.0.0.1:9000
# S3_BUCKET=rpi-cam
# S3_ACCESS_KEY_ID=rustfsadmin
# S3_SECRET_ACCESS_KEY=change-me-to-a-strong-password
Expand All @@ -27,17 +28,20 @@
#
# RUSTFS_ACCESS_KEY=rustfsadmin
# RUSTFS_SECRET_KEY=change-me-to-a-strong-password # required — RustFS won't start without it
# RUSTFS_API_BIND=127.0.0.1 # loopback-only by default; set a LAN IP only when intentionally exposing RustFS
# RUSTFS_CONSOLE_BIND=127.0.0.1 # loopback-only by default; set a LAN IP only when intentionally exposing RustFS

# ─── Observability (optional) ────────────────────────────────────────────────
# Ships structured logs (and optionally metrics) to a central Loki/Prometheus.
# Combine with standalone: COMPOSE_PROFILES=standalone,observability-ship
#
# COMPOSE_PROFILES=observability-ship
# LOKI_PUSH_URL=http://your-observability-host:3100/loki/api/v1/push
# PROMETHEUS_REMOTE_WRITE_URL=http://your-observability-host:9090/api/v1/write
# LOKI_PUSH_URL=https://your-observability-host/loki/api/v1/push
# PROMETHEUS_REMOTE_WRITE_URL=https://your-observability-host/api/v1/write
# PROMETHEUS_SCRAPE_API_KEY=CHANGE_ME # must also be in AUTHORIZED_API_KEYS
# OBSERVABILITY_INSTANCE=pi-01
# OTEL_ENABLED=true
# OTEL_EXPORTER_OTLP_ENDPOINT=http://your-observability-host:4318/v1/traces
# OTEL_EXPORTER_OTLP_ENDPOINT=https://your-observability-host:4318/v1/traces
# OTEL_SERVICE_NAME=relab-rpi-cam-plugin

# ─── Direct connection (local mode) ──────────────────────────────────────────
Expand All @@ -52,7 +56,8 @@
# LOCAL_ALLOWED_ORIGINS='["http://192.168.1.42"]' # extra CORS origins (rarely needed)

# ─── Advanced ────────────────────────────────────────────────────────────────
# AUTHORIZED_API_KEYS='["CHANGE_ME"]' # X-Api-Key auth; not needed for relay
# AUTHORIZED_API_KEYS='["CHANGE_ME"]' # X-Api-Key auth; needed for protected /metrics scraping
# APP_ENV=production # default; requires HTTPS for remote S3/OTLP endpoints
# CAMERA_DEVICE_NUM=0 # override if using a non-default camera
# BASE_URL=http://127.0.0.1:8018 # override if the Pi is at a different address
# ALLOWED_CORS_ORIGINS='["http://127.0.0.1:8000"]'
File renamed without changes.
48 changes: 12 additions & 36 deletions renovate.json → .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,28 @@
"semanticCommits": "enabled",
"semanticCommitType": "chore",
"semanticCommitScope": "deps",
"platformAutomerge": true,
"pep621": {
"enabled": true
},
"automerge": false,
"lockFileMaintenance": {
"enabled": true,
"automerge": true
"automerge": false,
"labels": [
"manual-review",
"security-sensitive"
]
},
"ignorePaths": [
".python-version"
],
"packageRules": [
{
"matchUpdateTypes": [
"minor",
"patch"
],
"automerge": true,
"labels": [
"automerge"
],
"matchPackageNames": [
"*"
]
},
{
"groupName": "github-actions",
"matchManagers": [
"github-actions"
],
"matchUpdateTypes": [
"digest",
"minor",
"patch"
],
"pinDigests": true,
"automerge": true,
"labels": [
"automerge",
"github-actions"
"github-actions",
"manual-review",
"security-sensitive"
]
},
{
Expand All @@ -58,16 +40,10 @@
"dockerfile",
"docker-compose"
],
"pinDigests": true
},
{
"groupName": "pre-commit",
"matchManagers": [
"pre-commit"
],
"automerge": true,
"labels": [
"automerge"
"docker",
"manual-review",
"security-sensitive"
]
}
],
Expand Down
21 changes: 7 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ jobs:
models: ${{ steps.filter.outputs.models }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
id: filter
with:
filters: |
models:
- 'relab_rpi_cam_models/**'
- 'tests/unit/test_contract_package.py'
- 'tests/unit/core/test_contract_package.py'
- '.github/workflows/models-check-reusable.yml'
- 'pyproject.toml'
- 'uv.lock'
Expand All @@ -50,6 +52,8 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
Expand All @@ -69,6 +73,8 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
Expand All @@ -85,19 +91,6 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false

audit:
name: Dependency Audit
if: github.event_name != 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
cache-dependency-glob: uv.lock
- run: uv audit --preview-features audit --locked --no-dev

models-check:
name: Models Check
needs: changes
Expand Down
14 changes: 4 additions & 10 deletions .github/workflows/models-check-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,23 @@ on:
required: false
type: string
default: "3.13"
runs_on:
required: false
type: string
default: "ubuntu-24.04"
upload_artifact:
required: false
type: boolean
default: false
artifact_name:
required: false
type: string
default: "relab-rpi-cam-models-dist"

permissions:
contents: read

jobs:
models-check:
name: relab-rpi-cam-models Checks
runs-on: ${{ inputs.runs_on }}
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false

- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
Expand Down Expand Up @@ -69,6 +63,6 @@ jobs:
if: inputs.upload_artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ inputs.artifact_name }}
name: relab-rpi-cam-models-dist
path: dist/relab-rpi-cam-models/*
retention-days: 7
3 changes: 2 additions & 1 deletion .github/workflows/models-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
Expand All @@ -34,7 +36,6 @@ jobs:
with:
python_version: "3.13"
upload_artifact: true
artifact_name: relab-rpi-cam-models-dist

publish:
name: Publish to PyPI
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ jobs:
if: steps.cz.outputs.next_version != steps.cz.outputs.previous_version
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create "${{ steps.cz.outputs.next_version }}" --title "${{ steps.cz.outputs.next_version }}" --generate-notes
run: gh release create "v${{ steps.cz.outputs.next_version }}" --title "v${{ steps.cz.outputs.next_version }}" --generate-notes
97 changes: 97 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
# spell-checker: ignore aquasecurity gacts SARIF

name: Security

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
schedule:
- cron: "0 3 * * 1"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
changes:
name: Detect Changes
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
container: ${{ steps.filter.outputs.container }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
id: filter
with:
filters: |
container:
- 'Dockerfile'
- 'pyproject.toml'
- 'uv.lock'

secret-scan:
name: Secret Scan
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
fetch-depth: 0
persist-credentials: false
- name: Run gitleaks
uses: gacts/gitleaks@c9a0338361dc45a01aa7ebaaa5330179f3c62873
with:
version: 8.30.1

dependency-audit:
name: Dependency Audit
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
cache-dependency-glob: uv.lock
- run: uv audit --preview-features audit --locked --no-dev

container-scan:
name: Container Scan
needs: changes
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || needs.changes.outputs.container == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
- name: Build image
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
file: Dockerfile
load: true
pull: true
tags: relab-rpi-cam-plugin:${{ github.sha }}
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25
with:
image-ref: relab-rpi-cam-plugin:${{ github.sha }}
format: table
exit-code: "1"
ignore-unfixed: true
severity: HIGH,CRITICAL
8 changes: 7 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repos:
args: [ "--markdown-linebreak-ext", "md" ] # Preserve Markdown hard line breaks.

- repo: https://github.com/gitleaks/gitleaks # Detect secrets in commits.
rev: v8.30.0
rev: v8.30.1
hooks:
- id: gitleaks

Expand Down Expand Up @@ -51,3 +51,9 @@ repos:
language: system
types: [ python ]
pass_filenames: false
- id: openapi-schema-check
name: openapi-schema-check
entry: uv run python -m scripts.export_openapi --check
language: system
files: ^(?:app/.*|scripts/export_openapi\.py|openapi\.rpi-cam\.json|justfile|pyproject\.toml|uv\.lock)$
pass_filenames: false
Loading
Loading