From bcf374665c5e259f55df645380d866204114ab92 Mon Sep 17 00:00:00 2001 From: Christophe Papazian Date: Tue, 21 Jul 2026 17:14:37 +0200 Subject: [PATCH] feat(appsec): report agentic onboarding marker in configuration telemetry (RFC-1113) Register DD_APPSEC_AGENTIC_ONBOARDING as an ordinary string configuration key whose raw value is reported verbatim in the app-started configuration telemetry via stableconfig.String. It is always emitted: unset reports an empty value with origin=default. No derived boolean and no read of AppSec's runtime-enabled state. Ports DataDog/dd-trace-dotnet#8920. Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/appsec/config/config.go | 10 ++++ internal/appsec/config/config_test.go | 48 ++++++++++++++++++++ internal/env/supported_configurations.gen.go | 1 + internal/env/supported_configurations.json | 7 +++ 4 files changed, 66 insertions(+) diff --git a/internal/appsec/config/config.go b/internal/appsec/config/config.go index 494358b06c4..43db5627cb8 100644 --- a/internal/appsec/config/config.go +++ b/internal/appsec/config/config.go @@ -19,6 +19,7 @@ import ( func init() { registerSCAAppConfigTelemetry() + registerAgenticOnboardingTelemetry() } // Register the global app telemetry configuration related to the Software Composition Analysis (SCA) product. @@ -32,12 +33,21 @@ func registerSCAAppConfigTelemetry() { } } +// registerAgenticOnboardingTelemetry reports [EnvAgenticOnboarding] verbatim in configuration +// telemetry (RFC-1113), always emitted: unset reports an empty value with origin=default. +func registerAgenticOnboardingTelemetry() { + stableconfig.String(EnvAgenticOnboarding, "") +} + // The following environment variables dictate the enablement of different the ASM products. const ( // EnvEnabled controls ASM Threats Protection's enablement. EnvEnabled = "DD_APPSEC_ENABLED" // EnvSCAEnabled controls ASM Software Composition Analysis (SCA)'s enablement. EnvSCAEnabled = "DD_APPSEC_SCA_ENABLED" + // EnvAgenticOnboarding is set by Datadog's agentic onboarding solution when it configures App & + // API Protection. It carries no behavior; its value is reported in configuration telemetry only. + EnvAgenticOnboarding = "DD_APPSEC_AGENTIC_ONBOARDING" ) // StartOption is used to customize the AppSec configuration when invoked with appsec.Start() diff --git a/internal/appsec/config/config_test.go b/internal/appsec/config/config_test.go index b4920aa86e5..3e23dc99a62 100644 --- a/internal/appsec/config/config_test.go +++ b/internal/appsec/config/config_test.go @@ -15,6 +15,54 @@ import ( "github.com/DataDog/dd-trace-go/v2/internal/telemetry/telemetrytest" ) +func TestAgenticOnboarding(t *testing.T) { + name := telemetry.EnvToTelemetryName(EnvAgenticOnboarding) + for _, tc := range []struct { + name string + envVarVal string + set bool + expectedValue string + expectedOrigin telemetry.Origin + }{ + { + name: "set-true", + envVarVal: "true", + set: true, + expectedValue: "true", + expectedOrigin: telemetry.OriginEnvVar, + }, + { + name: "set-arbitrary", + envVarVal: "false", + set: true, + expectedValue: "false", + expectedOrigin: telemetry.OriginEnvVar, + }, + { + name: "unset", + expectedValue: "", + expectedOrigin: telemetry.OriginDefault, + }, + } { + t.Run(tc.name, func(t *testing.T) { + if tc.set { + t.Setenv(EnvAgenticOnboarding, tc.envVarVal) + } + + expected := []telemetry.Configuration{{Name: name, Value: tc.expectedValue, Origin: tc.expectedOrigin}} + telemetryClient := new(telemetrytest.MockClient) + telemetryClient.On("RegisterAppConfigs", expected).Return() + defer telemetry.MockClient(telemetryClient)() + + registerAgenticOnboardingTelemetry() + + // Always emitted, even when unset (RFC-1113). + telemetryClient.AssertCalled(t, "RegisterAppConfigs", expected) + telemetryClient.AssertNumberOfCalls(t, "RegisterAppConfigs", 1) + }) + } +} + func TestSCAEnabled(t *testing.T) { for _, tc := range []struct { name string diff --git a/internal/env/supported_configurations.gen.go b/internal/env/supported_configurations.gen.go index 2e77843c777..b4e2cbee4e0 100644 --- a/internal/env/supported_configurations.gen.go +++ b/internal/env/supported_configurations.gen.go @@ -28,6 +28,7 @@ var SupportedConfigurations = map[string]struct{}{ "DD_API_SECURITY_REQUEST_SAMPLE_RATE": {}, "DD_API_SECURITY_SAMPLE_DELAY": {}, "DD_APM_TRACING_ENABLED": {}, + "DD_APPSEC_AGENTIC_ONBOARDING": {}, "DD_APPSEC_BODY_PARSING_SIZE_LIMIT": {}, "DD_APPSEC_ENABLED": {}, "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML": {}, diff --git a/internal/env/supported_configurations.json b/internal/env/supported_configurations.json index 2389eaf9b72..7a8183b4685 100644 --- a/internal/env/supported_configurations.json +++ b/internal/env/supported_configurations.json @@ -138,6 +138,13 @@ "default": "true" } ], + "DD_APPSEC_AGENTIC_ONBOARDING": [ + { + "implementation": "A", + "type": "string", + "default": "" + } + ], "DD_APPSEC_BODY_PARSING_SIZE_LIMIT": [ { "implementation": "B",