From 1c6525abf24b92dd97e16aae719920b39b2ca40b Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 20:09:27 -0700 Subject: [PATCH 1/7] add local protojson with permissive defaults --- utils/protojson/protojson.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 utils/protojson/protojson.go diff --git a/utils/protojson/protojson.go b/utils/protojson/protojson.go new file mode 100644 index 000000000..7aa27608c --- /dev/null +++ b/utils/protojson/protojson.go @@ -0,0 +1,29 @@ +package protojson + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +type MarshalOptions = protojson.MarshalOptions +type UnmarshalOptions = protojson.UnmarshalOptions + +func Format(m proto.Message) string { + return MarshalOptions{ + Multiline: true, + AllowPartial: true, + }.Format(m) +} + +func Marshal(m proto.Message) ([]byte, error) { + return MarshalOptions{ + AllowPartial: true, + }.Marshal(m) +} + +func Unmarshal(b []byte, m proto.Message) error { + return UnmarshalOptions{ + AllowPartial: true, + DiscardUnknown: true, + }.Unmarshal(b, m) +} From 883d64f5b56f806e1c9612d36a65ccd5f85730c7 Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 20:48:48 -0700 Subject: [PATCH 2/7] use local protojson --- auth/grants.go | 16 +++------------- observability/egressobs/egress.go | 2 +- utils/interceptors/curl.go | 3 ++- webhook/resource_url_notifier.go | 3 ++- webhook/url_notifier.go | 3 ++- webhook/verifier.go | 2 +- 6 files changed, 11 insertions(+), 18 deletions(-) diff --git a/auth/grants.go b/auth/grants.go index 8fc0bf00a..69719f7b9 100644 --- a/auth/grants.go +++ b/auth/grants.go @@ -22,25 +22,15 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" "golang.org/x/exp/slices" - "google.golang.org/protobuf/encoding/protojson" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" "github.com/livekit/protocol/utils" + "github.com/livekit/protocol/utils/protojson" ) type RoomConfiguration livekit.RoomConfiguration -var tokenMarshaler = protojson.MarshalOptions{ - EmitDefaultValues: false, -} - -// tokenUnmarshaler discards unknown fields so that older servers can accept -// tokens issued by newer clients that include fields the server does not yet know about. -var tokenUnmarshaler = protojson.UnmarshalOptions{ - DiscardUnknown: true, -} - var ErrSensitiveCredentials = errors.New("room configuration should not contain sensitive credentials") func (c *RoomConfiguration) Clone() *RoomConfiguration { @@ -51,11 +41,11 @@ func (c *RoomConfiguration) Clone() *RoomConfiguration { } func (c *RoomConfiguration) MarshalJSON() ([]byte, error) { - return tokenMarshaler.Marshal((*livekit.RoomConfiguration)(c)) + return protojson.Marshal((*livekit.RoomConfiguration)(c)) } func (c *RoomConfiguration) UnmarshalJSON(data []byte) error { - return tokenUnmarshaler.Unmarshal(data, (*livekit.RoomConfiguration)(c)) + return protojson.Unmarshal(data, (*livekit.RoomConfiguration)(c)) } // CheckCredentials checks if the room configuration contains sensitive credentials diff --git a/observability/egressobs/egress.go b/observability/egressobs/egress.go index a95abef49..3a1b5872f 100644 --- a/observability/egressobs/egress.go +++ b/observability/egressobs/egress.go @@ -3,7 +3,7 @@ package egressobs import ( "encoding/json" - "google.golang.org/protobuf/encoding/protojson" + "github.com/livekit/protocol/utils/protojson" "github.com/pkg/errors" diff --git a/utils/interceptors/curl.go b/utils/interceptors/curl.go index d64adf2cb..4169dcf27 100644 --- a/utils/interceptors/curl.go +++ b/utils/interceptors/curl.go @@ -8,8 +8,9 @@ import ( "sort" "github.com/twitchtv/twirp" - "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" + + "github.com/livekit/protocol/utils/protojson" ) // NewCurlPrinter creates a Twirp interceptor that prints a curl commands for each request made. diff --git a/webhook/resource_url_notifier.go b/webhook/resource_url_notifier.go index 8b88b38fc..011aeddb7 100644 --- a/webhook/resource_url_notifier.go +++ b/webhook/resource_url_notifier.go @@ -28,7 +28,8 @@ import ( "github.com/frostbyte73/core" "github.com/hashicorp/go-retryablehttp" - "google.golang.org/protobuf/encoding/protojson" + + "github.com/livekit/protocol/utils/protojson" "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" diff --git a/webhook/url_notifier.go b/webhook/url_notifier.go index 9317878e1..3dbe8ee64 100644 --- a/webhook/url_notifier.go +++ b/webhook/url_notifier.go @@ -28,7 +28,8 @@ import ( "github.com/frostbyte73/core" "github.com/hashicorp/go-retryablehttp" "go.uber.org/atomic" - "google.golang.org/protobuf/encoding/protojson" + + "github.com/livekit/protocol/utils/protojson" "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" diff --git a/webhook/verifier.go b/webhook/verifier.go index 69eda2111..ffca8f43c 100644 --- a/webhook/verifier.go +++ b/webhook/verifier.go @@ -21,7 +21,7 @@ import ( "io" "net/http" - "google.golang.org/protobuf/encoding/protojson" + "github.com/livekit/protocol/utils/protojson" "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" From 58bf250aad1aa6dab8eca7d5c8614cb02175fe8b Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 20:50:35 -0700 Subject: [PATCH 3/7] tidy --- webhook/resource_url_notifier.go | 3 +-- webhook/url_notifier.go | 3 +-- webhook/verifier.go | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/webhook/resource_url_notifier.go b/webhook/resource_url_notifier.go index 011aeddb7..895f9ed76 100644 --- a/webhook/resource_url_notifier.go +++ b/webhook/resource_url_notifier.go @@ -29,12 +29,11 @@ import ( "github.com/frostbyte73/core" "github.com/hashicorp/go-retryablehttp" - "github.com/livekit/protocol/utils/protojson" - "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" "github.com/livekit/protocol/utils" + "github.com/livekit/protocol/utils/protojson" ) const ( diff --git a/webhook/url_notifier.go b/webhook/url_notifier.go index 3dbe8ee64..ee96c376f 100644 --- a/webhook/url_notifier.go +++ b/webhook/url_notifier.go @@ -29,11 +29,10 @@ import ( "github.com/hashicorp/go-retryablehttp" "go.uber.org/atomic" - "github.com/livekit/protocol/utils/protojson" - "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" "github.com/livekit/protocol/logger" + "github.com/livekit/protocol/utils/protojson" ) type URLNotifierConfig struct { diff --git a/webhook/verifier.go b/webhook/verifier.go index ffca8f43c..45c24297f 100644 --- a/webhook/verifier.go +++ b/webhook/verifier.go @@ -21,10 +21,9 @@ import ( "io" "net/http" - "github.com/livekit/protocol/utils/protojson" - "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" + "github.com/livekit/protocol/utils/protojson" ) // Receive reads and verifies incoming webhook is signed with key/secret pair From da1b38b48124d9230b8d74a8f9a486e2ea8ee2d7 Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 20:51:12 -0700 Subject: [PATCH 4/7] Create great-birds-work.md --- .changeset/great-birds-work.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/great-birds-work.md diff --git a/.changeset/great-birds-work.md b/.changeset/great-birds-work.md new file mode 100644 index 000000000..b72d78585 --- /dev/null +++ b/.changeset/great-birds-work.md @@ -0,0 +1,5 @@ +--- +"@livekit/protocol": patch +--- + +add local protojson with permissive defaults From 8068a685608203a6df6d4d5deda6aef23544795b Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 20:52:33 -0700 Subject: [PATCH 5/7] reproduce comments --- utils/protojson/protojson.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/utils/protojson/protojson.go b/utils/protojson/protojson.go index 7aa27608c..22862910b 100644 --- a/utils/protojson/protojson.go +++ b/utils/protojson/protojson.go @@ -1,3 +1,7 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package protojson import ( @@ -8,6 +12,11 @@ import ( type MarshalOptions = protojson.MarshalOptions type UnmarshalOptions = protojson.UnmarshalOptions +// Format formats the message as a multiline string. +// This function is only intended for human consumption and ignores errors. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func Format(m proto.Message) string { return MarshalOptions{ Multiline: true, @@ -15,12 +24,18 @@ func Format(m proto.Message) string { }.Format(m) } +// Marshal writes the given [proto.Message] in JSON format using default options. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{ AllowPartial: true, }.Marshal(m) } +// Unmarshal reads the given []byte into the given [proto.Message]. +// The provided message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m proto.Message) error { return UnmarshalOptions{ AllowPartial: true, From 28e8855288d4b5b5ca1a54f6f2091b9071ab6076 Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 21:07:45 -0700 Subject: [PATCH 6/7] tidy --- utils/protojson/protojson.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/utils/protojson/protojson.go b/utils/protojson/protojson.go index 22862910b..a4496bb2c 100644 --- a/utils/protojson/protojson.go +++ b/utils/protojson/protojson.go @@ -24,18 +24,19 @@ func Format(m proto.Message) string { }.Format(m) } -// Marshal writes the given [proto.Message] in JSON format using default options. -// Do not depend on the output being stable. Its output will change across -// different builds of your program, even when using the same version of the -// protobuf module. +// Marshal writes the given [proto.Message] in JSON format using permissive +// options that avoid errors due to schema drift. Do not depend on the output +// being stable. Its output will change across different builds of your program, +// even when using the same version of the protobuf module. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{ AllowPartial: true, }.Marshal(m) } -// Unmarshal reads the given []byte into the given [proto.Message]. -// The provided message must be mutable (e.g., a non-nil pointer to a message). +// Unmarshal reads the given []byte into the given [proto.Message] using +// permissive options that avoid errors due to schema drift. The provided +// message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m proto.Message) error { return UnmarshalOptions{ AllowPartial: true, From 54d2d84fc69078aed65bf0350b38d63faa75358d Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Wed, 6 May 2026 22:31:32 -0700 Subject: [PATCH 7/7] add depguard lint rule --- .golangci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 8fc7a14e7..118a9463b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,8 +2,18 @@ version: "2" linters: default: none enable: + - depguard - staticcheck settings: + depguard: + rules: + protojson: + files: + - "$all" + - "!**/utils/protojson/**" + deny: + - pkg: google.golang.org/protobuf/encoding/protojson + desc: use github.com/livekit/protocol/utils/protojson instead — it sets DiscardUnknown by default to avoid schema-drift footguns staticcheck: checks: - "all" @@ -14,3 +24,5 @@ linters: - "-ST1022" - "-SA1019" - "-QF1008" + exclusions: + generated: strict