From 4be6333d020f540ffbae0607ff045cd212eb2aad Mon Sep 17 00:00:00 2001 From: juancarmore Date: Tue, 27 Oct 2026 17:05:00 +0100 Subject: [PATCH] openvidu-dashboard: the writer redacts custom base URLs --- .../redact-custom-base-url/.openspec.yaml | 2 + .../changes/redact-custom-base-url/design.md | 37 +++++++++++++++++++ .../redact-custom-base-url/proposal.md | 37 +++++++++++++++++++ .../specs/server-analytics-writer/spec.md | 22 +++++++++++ .../changes/redact-custom-base-url/tasks.md | 19 ++++++++++ 5 files changed, 117 insertions(+) create mode 100644 openvidu-dashboard/openspec/changes/redact-custom-base-url/.openspec.yaml create mode 100644 openvidu-dashboard/openspec/changes/redact-custom-base-url/design.md create mode 100644 openvidu-dashboard/openspec/changes/redact-custom-base-url/proposal.md create mode 100644 openvidu-dashboard/openspec/changes/redact-custom-base-url/specs/server-analytics-writer/spec.md create mode 100644 openvidu-dashboard/openspec/changes/redact-custom-base-url/tasks.md diff --git a/openvidu-dashboard/openspec/changes/redact-custom-base-url/.openspec.yaml b/openvidu-dashboard/openspec/changes/redact-custom-base-url/.openspec.yaml new file mode 100644 index 000000000..97e364202 --- /dev/null +++ b/openvidu-dashboard/openspec/changes/redact-custom-base-url/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-27 diff --git a/openvidu-dashboard/openspec/changes/redact-custom-base-url/design.md b/openvidu-dashboard/openspec/changes/redact-custom-base-url/design.md new file mode 100644 index 000000000..5748cda4f --- /dev/null +++ b/openvidu-dashboard/openspec/changes/redact-custom-base-url/design.md @@ -0,0 +1,37 @@ +# Design + +## Context + +- The codec copies a field of a protocol message only when the allow-list names it, with a rule per field. `redactURL` + rewrites a URL to scheme, host and path with the last segment replaced by `***`. +- `custom_base_url` has the rule `keep` in `RoomCompositeEgressRequest` and `TemplateSource`. The egress request + summary redacts it on its own, so only raw payloads hold the full value. + +## Goals / Non-Goals + +**Goals:** +- No stored payload holds the query string, userinfo or last path segment of a custom base URL. + +**Non-Goals:** +- Rewriting stored events. The read side of an edition may redact them again. + +## Decisions + +### Same rule as the web URL + +`custom_base_url` gets `redactURL`, the rule of `WebEgressRequest.url` and `WebSource.url`. A layout page under a +custom base URL is as likely as a web egress page to take a token in its query string or path. + +Alternative rejected: `stripURLCredentials`, which keeps the path. A token in the last path segment would survive. + +### Data model + +- Collections: `events` (payloads of `EGRESS_*` events). No field, type, index or retention change; no schema-version + change. +- Migration from legacy events: the legacy migration encodes with the same codec, so migrated payloads are redacted too. +- Performance: none. + +## Risks / Trade-offs + +- [The redacted value no longer opens the layout] → The value is shown for reference only; the request summary was + already redacted. diff --git a/openvidu-dashboard/openspec/changes/redact-custom-base-url/proposal.md b/openvidu-dashboard/openspec/changes/redact-custom-base-url/proposal.md new file mode 100644 index 000000000..cc8350272 --- /dev/null +++ b/openvidu-dashboard/openspec/changes/redact-custom-base-url/proposal.md @@ -0,0 +1,37 @@ +# Proposal + +## Why + +The writer stores the `custom_base_url` of room composite requests and of the template source of unified egress +requests unchanged in raw event payloads. A custom base URL can carry a token in its query string, while the request +summary of the egress document already stores it redacted. + +## What Changes + +- Raw event payloads store `custom_base_url` redacted like the web URL: no userinfo, query string or fragment, and the + last path segment replaced by `***`. + +Scope excludes the following: +- Raw events already stored, which keep the value until they expire. +- Any other field of the allow-list. + +Edition: CE and PRO (writer). Repositories: openvidu-livekit (`openvidu/analytics/schema/allowlist.go`) and the specs +of the dashboard. + +CHANGELOG: none. The analytics data model has not shipped in a release. + +## Capabilities + +### New Capabilities + +None. + +### Modified Capabilities + +- `server-analytics-writer`: the secrets allow-list redacts custom base URLs. + +## Impact + +- Writer: the allow-list rule of `custom_base_url` in `RoomCompositeEgressRequest` and `TemplateSource`, and the codec + tests. +- Dashboard: none; the request summary is unchanged. diff --git a/openvidu-dashboard/openspec/changes/redact-custom-base-url/specs/server-analytics-writer/spec.md b/openvidu-dashboard/openspec/changes/redact-custom-base-url/specs/server-analytics-writer/spec.md new file mode 100644 index 000000000..110066e26 --- /dev/null +++ b/openvidu-dashboard/openspec/changes/redact-custom-base-url/specs/server-analytics-writer/spec.md @@ -0,0 +1,22 @@ +## MODIFIED Requirements + +### Requirement: Secrets allow-list +Edition: CE and PRO. Projectors SHALL copy only fields named in an explicit allow-list into any document, +including raw payloads; every other field, present or future, SHALL be dropped. Egress stream, web, websocket and +custom base URLs SHALL be stored without userinfo, query string and fragment and with their last path segment replaced +by `***`; the ingress URL SHALL be stored without userinfo, query string and fragment. + +#### Scenario: Fully populated messages +- **GIVEN** an `AnalyticsEvent` of every type with every string field set to a unique sentinel, including `room.turn_password`, egress storage credentials, webhook signing keys, egress tokens, `ingress.stream_key`, `ingress.url`, SIP credentials and `api_call` request bodies +- **WHEN** each is projected with `store_metadata` and IP storage enabled +- **THEN** the sentinels found in all write models are exactly those of the allow-list paths + +#### Scenario: Stream URL redacted +- **GIVEN** an egress with stream URL `rtmps://user:pw@live.example.com/app/live_123?token=abc` +- **WHEN** it is projected +- **THEN** the stored output URL is `rtmps://live.example.com/app/***` + +#### Scenario: Custom base URL redacted +- **GIVEN** a room composite egress, and a unified egress with a template source, both with custom base URL `https://layouts.example.com/app/index.html?token=abc` +- **WHEN** their `EGRESS_STARTED` events are stored +- **THEN** each raw payload holds `custom_base_url: "https://layouts.example.com/app/***"` diff --git a/openvidu-dashboard/openspec/changes/redact-custom-base-url/tasks.md b/openvidu-dashboard/openspec/changes/redact-custom-base-url/tasks.md new file mode 100644 index 000000000..b5f38da8f --- /dev/null +++ b/openvidu-dashboard/openspec/changes/redact-custom-base-url/tasks.md @@ -0,0 +1,19 @@ +# Tasks + +## 1. Writer (openvidu-livekit) + +- [x] 1.1 Give `custom_base_url` the `redactURL` rule in `RoomCompositeEgressRequest` and `TemplateSource` of + `openvidu/analytics/schema/allowlist.go`. Verify with a codec test that encodes both requests with a custom base + URL carrying a token, and with the codec suite. +- [x] 1.2 Add a custom base URL with a secret to the room composite egress of the writer test builders, so that the + integration suite's no-secret check covers it. Verify with the analytics integration tests and the lint of the + fork. + +## 2. Docs and CHANGELOG + +- [x] 2.1 No CHANGELOG line: the analytics data model has not shipped. No `AGENTS.md` changes. Verify by reading the + change against both files. + +## 3. Integration check + +- [x] 3.1 Run the spec validation and the format check of the dashboard. Verify that they pass.