diff --git a/Cargo.lock b/Cargo.lock index e16c9c170..b4358be26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "arbitrary" @@ -1206,9 +1206,9 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2e9b7adf77fa02204d4d523ae4f171b6591c2632b030865336335c7d7b420e" +checksum = "03b4982ef9fa54ec9eee841e891e7ddc5434be1250e88de31572e000c888f30b" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -1216,9 +1216,9 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f09d9f397eae612ac15becf0e0b2165d2232003f4f2a1549572a724d1c48c5" +checksum = "529143118c4eeb58c39ecb02319557d512be6c61348486422974ab8e3906b8a8" dependencies = [ "serde", "serde_derive", @@ -1227,9 +1227,9 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e004cf1270abc82f7b9fb32d1a9d73a1cc0d5a0215b97db8c32658748e78b01" +checksum = "b7780677247ad3577e3a6a3ebf43f39b325a11d6393db72b2c9968a910d4d13d" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -1258,9 +1258,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f32034641f96b123e4fdb5666e726d9f252e222638fc8fdd905b4ff18c3c4e" +checksum = "ac9645250416cbf92454fe61160e17e026e0ce405906a54500b114f923ddffc9" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -1286,9 +1286,9 @@ dependencies = [ [[package]] name = "cranelift-entity" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "341d5e1e071320505ebbc8194a8eb61fa94394b1ed93ba3cbec3be5fa1c3c1ce" +checksum = "a5300c49cf940526fe771517b3b3eabd5d0ff164ee61698579cf403fe8d3af3c" dependencies = [ "cranelift-bitset", "serde", @@ -1298,9 +1298,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c6f3e2419ecb54a5503994d35421554c5e487d0493bc86ea96907bab51fd29" +checksum = "da4adbf760207fdbbe130f1191cce01cdef66831a9f648b1f39ff2800d126d45" dependencies = [ "cranelift-codegen", "hashbrown 0.17.1", @@ -1311,15 +1311,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21aa47a5e0b1e9fb2c9348459088d5dbb872ebe17781ada1270d8364c7e73257" +checksum = "8315b21ff018226a42a60a4702c2dd75f6447cac26e9bca622e14c22088c2ff5" [[package]] name = "cranelift-native" -version = "0.133.0" +version = "0.133.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3054a03ac285b170662ec9530602b01cd394a7428cd753b48d9cae51f05249a" +checksum = "d506ef23a60715bde451b06620b14402166ded3b648454fccbf04f3e46a4aa70" dependencies = [ "cranelift-codegen", "libc", @@ -1863,7 +1863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -2990,7 +2990,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -4791,7 +4791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.118", @@ -4817,9 +4817,9 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "047bda68096e5f290619ce037b7c3fa352d11f08edf0fce3030c351adc0f8ec0" +checksum = "38b92604caae1a1899b6a5b54967289dd538177c626004c91accf9d0ec7e4a12" dependencies = [ "cranelift-bitset", "log", @@ -4829,9 +4829,9 @@ dependencies = [ [[package]] name = "pulley-macros" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83258a9bcc97d3fb15bf4e1c43bc2cc85c718e3563a697f145f245e651f2828f" +checksum = "5a7ac85c0bb3fb351f10d531230aaa5e366b46d7c4e5328e5f02801d6dac1165" dependencies = [ "proc-macro2", "quote", @@ -5662,7 +5662,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -5731,7 +5731,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -5752,7 +5752,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -6896,7 +6896,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -8002,9 +8002,9 @@ dependencies = [ [[package]] name = "wasmtime" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08dd5caf09eda1d523261a0dd421a54e3bb165cf6f5b02c82327e712d49e3cf4" +checksum = "c4213d2f019a5e44aa8a61d8826dd33a505bff79f749b14a8bafd67321cb9351" dependencies = [ "addr2line 0.26.1", "async-trait", @@ -8055,9 +8055,9 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f3aa689689cf295568aa4d24ab636579fb3b36dfa7cea35020d87064fc88ec" +checksum = "d45863de41977ec6453e859cf843d456fa3fcb45a659b66d16e794f90ec4f5b7" dependencies = [ "anyhow", "cpp_demangle", @@ -8086,9 +8086,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-cache" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6c27fbabb7df6c88a592a28773a92aa8cfba5ee656963d7ad9b32a8f57a3d8" +checksum = "438bc7dc45fb75297d75f79a9a0ce852345d13ebc6a6863f6f688f013836a9dd" dependencies = [ "base64 0.22.1", "directories-next", @@ -8106,9 +8106,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-macro" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de4451ab437d7b2d41e637a4379e87ff76aeeb051236064dcc75c1855714ee58" +checksum = "f1e48f8d4966d62a10b6d70722bc432c1e163890be2801d3b5784589ad36ffc3" dependencies = [ "anyhow", "proc-macro2", @@ -8121,15 +8121,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-util" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b5e357002645964342b99a6fe8405cda7dd031f498927992c9d99d5012daa7" +checksum = "819ad5abd5822a22dbf4014475cdfd1fe790707761cd732d74aaa3ba4d5ba489" [[package]] name = "wasmtime-internal-core" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f6ce74d60a8ed870548e7efa9710c54f982bbfcf80e5ee5eee8498318616483" +checksum = "3fc28372e36eaf8cf70faa83b5779137f7e99c8d18569a125d1580e735cc9e4d" dependencies = [ "anyhow", "hashbrown 0.17.1", @@ -8139,9 +8139,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-cranelift" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24204583d847b7ce3d770f7a3456739d5d43f65c884cb47111dbe27b26ebbe6" +checksum = "a433efc6e35112a5457e1dc8bc4d8d39820ac7722267e89bc04e5df641f32124" dependencies = [ "cfg-if", "cranelift-codegen", @@ -8166,9 +8166,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-fiber" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecaeb13bf3eb94a02e32ea3842c8fda3ea6897c299745100c1230b65769d2d91" +checksum = "18a1d3a39d0d210f6b8574ee96a4315e0a14c67f3a1fc3cd5372cb10d2fb4422" dependencies = [ "cc", "cfg-if", @@ -8181,9 +8181,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5090e9a302bb5729a84766e4af07b6b10efe733e437bc266dd954a957114df63" +checksum = "9f667288cb4dfa68a4639ffac4d5628535dda64ebdc2b990526efb12b30ba803" dependencies = [ "cc", "object 0.39.1", @@ -8193,9 +8193,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bba33d9d951a9a974a866e80c864a9a46b28086e369582e0caa78e14a9f29e4" +checksum = "eba651d44ab0faad4c58106b3adb45068189fb65ef50f0c404b6d9e3bf81a357" dependencies = [ "cfg-if", "libc", @@ -8205,9 +8205,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-unwinder" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695063a19bac17895f95c0c0f2f9544e85a277763cd77b5778f0cce6a971073e" +checksum = "2ecc52563b0558af2a7487eb710de07cc4532564b55528876129238e83118cb1" dependencies = [ "cfg-if", "cranelift-codegen", @@ -8218,9 +8218,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc77f7513209b76e8f4772af640819f47fca3a5425b4417ef9c20b888334063c" +checksum = "e747f4a074699ba1b4e4d841fb263f9b7df5bd1555181c4752bf5990d21ba676" dependencies = [ "proc-macro2", "quote", @@ -8229,9 +8229,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-wit-bindgen" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859103d8336304b8beebbf89a620c2f53a118fd5fbce41bc572cf4bacc8111d" +checksum = "80009f46991622814196d96fac6fc0a938f46b5cba737a8f4e21e24e5a03856f" dependencies = [ "anyhow", "bitflags 2.13.0", @@ -8242,9 +8242,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093c67243785465fdab0cb8bfada4a1171a543dfc22b392201c77d8086367b58" +checksum = "e9f65ef30a2c5478873cdb619085a7a649d3ce41cc3eaf298a7ce3dee96a8e11" dependencies = [ "async-trait", "bitflags 2.13.0", @@ -8271,9 +8271,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi-io" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95db6ca70bd5b7aab6b0297419ccbdb88682e12cc37764c757f58e917da650b9" +checksum = "cee57d5fef4976b1ab542615f4cef2c43278eb549d8078939668ea0f13d5c696" dependencies = [ "async-trait", "bytes", @@ -8627,9 +8627,9 @@ dependencies = [ [[package]] name = "wiggle" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "860468238360805e56e88335d892df427ad7a6908f4a83d96d7a391460346025" +checksum = "e03df88bf1a6068b02851aa3ef9427d285118f5c1c153b068a8995c69dd9562a" dependencies = [ "bitflags 2.13.0", "thiserror 2.0.18", @@ -8641,9 +8641,9 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a128aae0b85cf03726242fad62c5b00c7d1ad809f18883a2338a0c3d5ae1fb" +checksum = "e014aec8661b613154377e4b49dbbb0dfc4f424efcee749782054576c00537d9" dependencies = [ "heck", "proc-macro2", @@ -8655,9 +8655,9 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "46.0.0" +version = "46.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf3c6a6e1a110be73fcfe10ab9456f0b1bf5a1020010e66d536502baf70a36b" +checksum = "f67310a8ae5190b7f3dcacf8697f2890701a3a8427b3e77ed91d3632dcedaceb" dependencies = [ "proc-macro2", "quote", @@ -8693,7 +8693,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] diff --git a/apps/skit/src/config.rs b/apps/skit/src/config.rs index 7aed38349..03438539f 100644 --- a/apps/skit/src/config.rs +++ b/apps/skit/src/config.rs @@ -1677,6 +1677,27 @@ allowed_plugins = [] }); } + #[test] + fn config_partial_role_override_deep_merges_builtin() { + figment::Jail::expect_with(|jail| { + jail.create_file( + "skit.toml", + r#"[permissions.roles.user] +allowed_nodes = ["video::*", "containers::*", "transport::http::mse", "plugin::*"] +"#, + )?; + let result = load("skit.toml").expect("load with user override"); + let user = result.config.permissions.roles.get("user").expect("user role"); + // Fields absent from the TOML must survive from the built-in default + // (deep-merge), not reset to the struct's bool default of false. + assert!(user.create_sessions, "create_sessions preserved by deep-merge"); + assert!(user.destroy_sessions, "destroy_sessions preserved by deep-merge"); + // The overridden array adds the MSE transport node. + assert!(user.is_node_allowed("transport::http::mse")); + Ok(()) + }); + } + fn attr_policy(allowed: &[&str], fallback: &str) -> MetricsAttributePolicy { MetricsAttributePolicy { allowed: allowed.iter().map(|s| (*s).to_string()).collect(), diff --git a/deny.toml b/deny.toml index 6ea3b8f97..8716fd741 100644 --- a/deny.toml +++ b/deny.toml @@ -81,6 +81,22 @@ ignore = [ # an unmaintained notice; CMake 4.0 build-error risk is mitigated since # CI pins an earlier CMake. { id = "RUSTSEC-2026-0150", reason = "transitive dep via opus crate; no safe upgrade available" }, + + # ttf-parser is unmaintained (author archived the crate). Transitive dep of + # fontdue, which streamkit-nodes uses for text rasterization. No safe upgrade + # is available per the advisory; migrating fontdue->skrifa is tracked in + # https://github.com/streamer45/streamkit/issues/642. No security + # vulnerability, just an unmaintained notice. + { id = "RUSTSEC-2026-0192", reason = "transitive dep via fontdue; no safe upgrade available" }, + + # quick-xml 0.39 DoS advisories (quadratic duplicate-attribute check and + # unbounded NsReader namespace allocation). Transitive dep via opendal, whose + # latest release (0.57) pins quick-xml 0.39, so no upgrade path exists yet + # (fixed in quick-xml >= 0.41). Exposure is limited to XML responses from the + # operator-configured S3 endpoint, not attacker-supplied input. Removal is + # tracked in https://github.com/streamer45/streamkit/issues/647. + { id = "RUSTSEC-2026-0194", reason = "transitive dep via opendal; no upgrade path; only parses configured S3 endpoint responses" }, + { id = "RUSTSEC-2026-0195", reason = "transitive dep via opendal; no upgrade path; only parses configured S3 endpoint responses" }, ] # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. diff --git a/examples/web-capture/.gitignore b/examples/web-capture/.gitignore new file mode 100644 index 000000000..9064eb2e2 --- /dev/null +++ b/examples/web-capture/.gitignore @@ -0,0 +1 @@ +/gateway diff --git a/examples/web-capture/.golangci.yml b/examples/web-capture/.golangci.yml new file mode 100644 index 000000000..e4ee18ab0 --- /dev/null +++ b/examples/web-capture/.golangci.yml @@ -0,0 +1,26 @@ +version: "2" +linters: + default: none + enable: + - bidichk + - errcheck + - govet + - ineffassign + - makezero + - misspell + - revive + - staticcheck + - unconvert + - unqueryvet + - unused + - whitespace + settings: + govet: + disable: + - fieldalignment + enable-all: true + unqueryvet: + check-sql-builders: true +issues: + max-issues-per-linter: 0 # no maximum + max-same-issues: 0 # no maximum diff --git a/examples/web-capture/Dockerfile b/examples/web-capture/Dockerfile new file mode 100644 index 000000000..8c86de183 --- /dev/null +++ b/examples/web-capture/Dockerfile @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: © 2025 StreamKit Contributors +# +# SPDX-License-Identifier: MPL-2.0 + +FROM golang:1.24-bookworm AS build +WORKDIR /src +COPY . . +RUN CGO_ENABLED=0 go build -o /gateway ./cmd/gateway + +FROM gcr.io/distroless/static-debian12 +COPY --from=build /gateway /gateway +EXPOSE 8080 +ENTRYPOINT ["/gateway"] diff --git a/examples/web-capture/Makefile b/examples/web-capture/Makefile new file mode 100644 index 000000000..e0e112efb --- /dev/null +++ b/examples/web-capture/Makefile @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: © 2025 StreamKit Contributors +# +# SPDX-License-Identifier: MPL-2.0 + +.PHONY: build lint test run clean + +build: + go build -o gateway ./cmd/gateway + +lint: + golangci-lint run + +test: + go test ./... + +run: + go run ./cmd/gateway + +clean: + rm -f gateway diff --git a/examples/web-capture/README.md b/examples/web-capture/README.md new file mode 100644 index 000000000..9ebc4bcfb --- /dev/null +++ b/examples/web-capture/README.md @@ -0,0 +1,117 @@ + + +# Web Capture Gateway + +Render any web page to video through a StreamKit backend. The first path segment picks the output; paste the target URL after it — no flags, no JSON: + +- **clip** — a finite MP4 file (oneshot pipeline): `web.streamkit.dev/clip/example.com` +- **cast** — a live stream, WebM or fMP4 (dynamic session): `web.streamkit.dev/cast/example.com` + +The page is rendered by the [Servo](../../plugins/native/servo) browser engine on the backend. The gateway turns a pasteable URL into the multipart oneshot / dynamic-session calls the backend expects and, for `cast`, owns the session lifetime so abandoned streams are torn down instead of leaking a renderer. + +## URL shape + +``` +{host}/{clip|cast}/[options/]{target-url} +``` + +The first segment is the output (`clip` or `cast`); the target URL follows **verbatim** (scheme optional, `https` assumed), so its own query string just rides along — no percent-encoding: + +``` +web.streamkit.dev/clip/grafana.example/d/abc?panel=3&from=now-6h +``` + +Options are an optional comma-separated `key=value` segment between the output and the URL: + +``` +web.streamkit.dev/clip/dur=30s/example.com # clip length (default 10s, capped at 60s) +web.streamkit.dev/cast/res=2560x1440/example.com # capture resolution (default 1920x1080) +web.streamkit.dev/clip/res=1280x720,dur=15s/example.com # combine, comma-separated +``` + +`dur` is `clip`-only; `res` (the capture resolution) applies to both modes. The scheme is identical locally, e.g. `http://127.0.0.1:8080/clip/dur=5s/example.com`. + +The same URL serves a browser and a player/script: an address-bar visit (`Accept: text/html`) to a `cast` URL returns a tiny autoplay page; anything else (a `