(go/redacted):build !integration
// Formal test suite for specs/otel-observability-spec.md v0.4.0.
// Notation: TLA+/Z3/F* (illustrative). Predicates P1–P15 listed in file header.
// Run: go test ./pkg/workflow/... -run Formal
package workflow
import (
"encoding/json"
"strings"
"testing"
"github.com/github/gh-aw/pkg/constants"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// P4 — §5.5 if-missing policy accepts exactly error/warn/ignore; invalid → "".
func TestFormal_IfMissingPolicyValidation(t *testing.T) {
cases := []struct{ in, want string }{
{"error", "error"}, {"warn", "warn"}, {"ignore", "ignore"},
{"Error", "error"}, {"WARN", "warn"}, {" warn ", "warn"},
{"", ""}, {"fail", ""}, {"silent", ""}, {"skip", ""},
}
for _, c := range cases {
t.Run("mode="+c.in, func(t *testing.T) {
assert.Equal(t, c.want, normalizeOTLPIfMissingMode(c.in),
"P4: if-missing %q must normalize to %q", c.in, c.want)
})
}
}
// P3 — §5.4 Authorization → x-sentry-auth on Sentry endpoints only.
func TestFormal_SentryAuthHeaderRewrite(t *testing.T) {
tests := []struct {
name, ep, wantContain, wantMissing string
headers any
}{
{"sentry HTTPS rewrites", "https://ingest.sentry.io/123",
map[string]any{"Authorization": "Sentry key=abc"},
"x-sentry-auth=", "Authorization="},
{"non-sentry preserves", "(traces.datadog.com/redacted)",
map[string]any{"Authorization": "Bearer tok"},
"Authorization=", "x-sentry-auth="},
{"well-known sentry secret rewrites",
"${{ secrets." + constants.OTELSentryEndpointSecretName + " }}",
map[string]any{"Authorization": "Sentry key=xyz"},
"x-sentry-auth=", "Authorization="},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := normalizeOTLPHeadersForEndpoint(tt.headers, tt.ep)
assert.Contains(t, r, tt.wantContain, "P3: %q", tt.ep)
assert.NotContains(t, r, tt.wantMissing, "P3: %q", tt.ep)
})
}
}
// P10 — §14.1 stable Level 2 mirror path contract.
func TestFormal_MirrorPathConstant(t *testing.T) {
assert.Equal(t, "/tmp/gh-aw/otel.jsonl",
constants.TmpGhAwDir+"/"+constants.OtelJsonlFilename,
"P10: mirror path must be /tmp/gh-aw/otel.jsonl per spec §14.1")
}
// P9 — §16.3 / §6.4 fan-out preserves declaration order.
func TestFormal_FanOutPreservesDeclarationOrder(t *testing.T) {
declared := []string{"(primary.example.com/redacted)", "(secondary.example.com/redacted)", "(tertiary.example.com/redacted)"}
eps := make([]any, len(declared))
for i, u := range declared {
eps[i] = map[string]any{"url": u}
}
entries := collectAllOTLPEndpoints(map[string]any{"observability": map[string]any{"otlp": map[string]any{"endpoint": eps}}})
require.Len(t, entries, len(declared), "P9: all declared endpoints must be preserved")
for i, e := range entries {
assert.Equal(t, declared[i], e.URL, "P9: endpoint %d must match declaration order", i)
}
}
// Encoding — §6.1 GH_AW_OTLP_ENDPOINTS must be valid compact JSON array.
func TestFormal_EndpointEncoding(t *testing.T) {
assert.Empty(t, encodeOTLPEndpoints(nil), "empty endpoints → empty string")
entries := []otlpEndpointEntry{{URL: "(p.example.com/redacted)", Headers: "K=V"}, {URL: "(b.example.com/redacted)"}}
raw := encodeOTLPEndpoints(entries)
var dec []map[string]any
require.NoError(t, json.Unmarshal([]byte(raw), &dec))
require.Len(t, dec, 2)
assert.Equal(t, "(p.example.com/redacted)", dec[0]["url"])
_, hasH := dec[1]["headers"]
assert.False(t, hasH, "headers omitted when empty")
}
Summary
specs/otel-observability-spec.mdv0.4.0 defines the compatibility-first OpenTelemetry observability contract forgh-aw: OTLP endpoint normalization, header secrecy, Sentry rewriting,if-missingpolicy, service-name formation, domain extraction, local mirror invariants, and fan-out ordering. This formalization derives 15 predicates (TLA+, Z3/SMT-LIB, F*) and maps each to a Go testify unit test inpkg/workflow/.Specification
specs/otel-observability-spec.mdobservability.otlpcompiler + runtime contract, Levels 1 & 2 (§2.3)Formal Model
Predicates and invariants (illustrative notation)
Behavioral Coverage Map
P1 EndpointFormNormalizationTestFormal_EndpointFormNormalizationP2 HeaderMapDeterminismTestFormal_HeaderMapDeterminismP3 SentryAuthHeaderRewriteTestFormal_SentryAuthHeaderRewriteAuthorization→x-sentry-authon Sentry; preserved elsewhereP4 IfMissingPolicyValidationTestFormal_IfMissingPolicyValidation""P5 ServiceNameFormationTestFormal_ServiceNameFormation"gh-aw"or"gh-aw.<sanitized-id>"; WorkflowID > NameP6 StaticDomainExtractionTestFormal_StaticDomainExtraction""P7 ExpressionNoAllowlistEntryTestFormal_ExpressionProducesNoAllowlistEntry${{ ... }}→ empty domain (no allowlist entry)P8 TopLevelHeadersStringFormOnlyTestFormal_TopLevelHeadersApplyToStringFormOnlyP9 FanOutPreservesOrderTestFormal_FanOutPreservesDeclarationOrderP10 MirrorPathConstantTestFormal_MirrorPathConstant/tmp/gh-aw/otel.jsonlstable Level 2 constantP11 EmptyURLEntryDiscardedTestFormal_EmptyURLEntriesDiscardedP12 NonSentryHeaderPreservationTestFormal_StringHeaderFormPreservedForNonSentryP13 NilHeadersNormalizeTestFormal_NilAndEmptyHeadersYieldEmptyString""/{}→""without panicP14 InvalidIfMissingIsDefaultTestFormal_InvalidIfMissingFallsBackToDefault""(error default)P15 AbsentObservabilityNoExportTestFormal_AbsentObservabilityProducesNoEndpointsGenerated Test Suite
📄 `pkg/workflow/otel_observability_formal_test.go` (key tests — full file in repo)
Usage
pkg/workflow/otel_observability_formal_test.go(committed in this run).go test ./pkg/workflow/... -run FormalContext
specs/otel-observability-spec.mdpkg/workflow/observability_otlp.goWarning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
proxy.golang.orgSee Network Configuration for more information.