Skip to content

chore: harden minor release readiness - #5

Merged
RyleaStark merged 1 commit into
ci/dependency-maintenancefrom
audit/minor-release-readiness
Aug 4, 2026
Merged

chore: harden minor release readiness#5
RyleaStark merged 1 commit into
ci/dependency-maintenancefrom
audit/minor-release-readiness

Conversation

@RyleaStark

Copy link
Copy Markdown
Owner

Summary

Prepares lnSwitchboard for its next minor release without changing VERSION or publishing images.

This is the fourth layer in the dependency/release stack:

  1. chore(deps): refresh frontend dependencies #1 — frontend dependency and security refresh
  2. chore(deps): refresh backend dependencies #2 — backend runtime dependency refresh
  3. ci(deps): automate dependency maintenance #3 — dependency automation, security gates, current Actions, and pinned toolchains
  4. This PR — application, container, documentation, and release-readiness audit/fixes
  5. Follow-up — version bump and multi-architecture publication

Base: #3

Application and compatibility

  • replaces deprecated Starlette HTTP_422_UNPROCESSABLE_ENTITY constants
  • uses audited httpx2==2.9.1 for FastAPI/Starlette's supported test-client bridge and makes Starlette deprecations test failures
  • adds durable protobuf 7 wire-roundtrip and websockets 17 relay compatibility tests
  • requires a matching positive Nostr relay ACK; timeouts, malformed replies, notices, wrong IDs, and rejections now fail delivery
  • closes every short-lived SQLite connection deterministically, including Python 3.13 resource-warning coverage
  • persists dashboard environment changes without replacing live clients/stores underneath running background workers; the UI now tells operators to restart before changes apply
  • adds SPA deep-link coverage and route-level lazy loading, reducing the previous ~914 KB monolithic bundle to bounded route chunks
  • cleans the noisy Vitest mock warning

Security boundaries

  • removes permissive global CORS from the admin API while retaining the NIP-05 endpoint's required CORS response
  • ignores forwarded/client-IP headers unless the immediate proxy is explicitly trusted via TRUSTED_PROXY_CIDRS
  • disables Uvicorn's independent proxy-header processing so there is one auditable trust boundary
  • binds the Compose host port to 127.0.0.1 by default; LNSWITCHBOARD_BIND_ADDRESS is the explicit opt-out
  • rejects untrusted HTTP Host values through an explicit TRUSTED_HOSTS allowlist, preventing loopback DNS rebinding
  • blocks private, loopback, link-local, reserved, and mixed public/private DNS destinations for outbound webhooks and Nostr relays by default
  • provides explicit ALLOW_PRIVATE_WEBHOOKS and ALLOW_PRIVATE_NOSTR_RELAYS escape hatches for intentional trusted local services
  • documents the admin UI/API reverse-proxy and same-origin deployment boundary

Container and release hardening

  • pins Python and Node base images to their current multi-architecture index digests
  • pins pip 26.2, Buildx 0.36.0, BuildKit v0.32.1 by digest, and binfmt by digest
  • adds .python-version and .nvmrc for local toolchain parity
  • removes obsolete Compose schema metadata
  • adds an OCI health check and a real CI container runtime/health smoke test
  • removes the manual publish override, prevents release runs from being cancelled mid-flight, and makes partial cross-registry publication safely resumable without overwriting version tags
  • publishes SBOM and max-mode provenance attestations on the release path
  • verifies GHCR and Docker Hub version tags before promoting them to latest, then confirms all tags share one digest, contain linux/amd64 and linux/arm64, and carry the expected OCI version/revision labels
  • verifies the existing 0.2.3 GHCR and Docker Hub manifests currently share the same multi-architecture digest

Operator migration notes

  • Compose now listens on host loopback by default. Set LNSWITCHBOARD_BIND_ADDRESS only when another interface is intentional.
  • Public/reverse-proxy hostnames must be listed in TRUSTED_HOSTS.
  • Forwarding headers are ignored until the immediate proxy IP/CIDR is listed in TRUSTED_PROXY_CIDRS.
  • Private webhook/relay targets require their explicit opt-in environment variable.
  • Dashboard environment edits are persisted immediately and applied after restarting lnSwitchboard.

Verification

  • Python 3.11.15: pip check, Ruff, pytest 123/123, combined runtime/development pip-audit
  • Python 3.13.5: pytest with ResourceWarnings promoted to errors
  • Node 22.23.1: npm audit (0 vulnerabilities), ESLint, Vitest 32/32, production build
  • actionlint 1.7.12
  • docker compose config --quiet
  • existing published 0.2.3 cross-registry manifest verification
  • local Uvicorn health and SPA/lazy-route browser smoke
  • tracked plus untracked credential scan with findings manually triaged as template-variable/test literals only

Deliberately deferred

  • VERSION remains 0.2.3; the follow-up release PR owns the bump and publication.
  • The runtime image still runs as root because changing UID/GID would break existing writable bind mounts without a documented ownership migration. That should be handled as a separate compatibility change.
  • Application-native admin authentication remains out of scope; the supported boundary is loopback/VPN/reverse-proxy authentication, now safer by default and explicitly documented.

@RyleaStark
RyleaStark merged commit 6a592d1 into main Aug 4, 2026
5 checks passed
@RyleaStark
RyleaStark deleted the audit/minor-release-readiness branch August 4, 2026 01:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant