Loading
feat(config): add the usage_data config fragment (S23 Step 1)
What
Step 1 of the S23 usage data foundation plan: the usage_data configuration fragment.
UsageDataConfig/GitLabStandardConfigproto messages (Configtag 14). Allcollector_urlvalidation is message-level CEL gated onenabled(required-when-enabled,isUri, https outsideenvironment: development), so a disabled section loads with every field unset.- Runtime conversion (
usageDataFromProto) with theapp_iddefault; an absent block yields the zero value (emission disabled, privacy-safe). - Commented-out
config.example.yamlsection.
Also patches the spec's Configuration section in the same MR (spec gap found during implementation): gitlab_standard.environment is now allow-listed (production/staging/development), mirroring the realm rule. Previously a typo like prod loaded silently and would misclassify analytics.
Spec coverage
Spec: docs/specs/S23-usage-data-collection.md
Acceptance criteria
| # | Criterion | Tests |
|---|---|---|
| AC-1 | Disabled/omitted section: Track and lifecycle succeed, no HTTP | Config half: TestLoad_UsageData_AbsentBlockYieldsZeroValue, TestLoad_UsageData_DisabledSectionLoads. Tracker: Step 2. |
| AC-2 | Track produces collector POST with both context schema URIs | Owned by Step 2 (internal/usagedata). Not tested in this MR. |
| AC-3 | ar_instance_version equals app.Version, not settable via Attrs |
Owned by Step 2. Not tested in this MR. |
| AC-4 | correlation_id equals the request's correlation ID |
Owned by Step 2. Not tested in this MR. |
| AC-5 | Out-of-enum RepositoryKind/UpstreamType drops + counts |
Owned by Step 2. Not tested in this MR. |
| AC-6 | Forced gitlab_standard validation failure drops through same path |
Owned by Step 2. Not tested in this MR. |
| AC-7 | Shutdown delivers queued events; bounded when unreachable | Owned by Step 2. Not tested in this MR. |
| AC-8 | Track safe under concurrent use (race test) | Owned by Step 2. Not tested in this MR. |
| AC-9 | Successful S17 create emits exactly one event; failed create none | Owned by Step 5. Not tested in this MR. |
| AC-10 | Emitter metrics under service prefix; dropped counter registered | Owned by Step 3. Not tested in this MR. |
Error cases
| # | Condition | Tests |
|---|---|---|
| E-1 | Malformed/non-https collector_url, enabled without required fields, or values outside the allow-lists: load fails |
TestLoad_UsageData_ValidationRejections (8 cases); boundaries pinned by TestLoad_UsageData_HTTPAllowedInDevelopment, TestLoad_UsageData_AcceptsAllowedRealms, TestLoad_UsageData_AcceptsProductionEnvironment |
| E-2 | Collector unreachable at runtime: retry/queue/drop, Track never blocks | LabKit-owned emitter internals; Track/shutdown seams owned by Step 2. Not tested in this MR. |
| E-3 | Context validation failure: drop + counter + log | Owned by Step 2. Not tested in this MR. |
| E-4 | Track after Shutdown: no-op, reason="stopped" |
Owned by Step 2. Not tested in this MR. |
| E-5 | Process exit with queued events: events lost | Accepted data loss per ADR-012; deliberately untested (no falsifiable assertion). |
Security considerations
| # | Concern | Tests |
|---|---|---|
| S-1 | No tokens, credentials, or raw PII in payloads | Owned by Steps 2/5 (payload assembly). Not tested in this MR. |
| S-2 | Props limited to ADR-012 catalog dimensions |
Review-enforced per spec; no automated test. |
| S-3 | Attrs cannot carry instance version, correlation ID, or identity |
Owned by Step 2 (type surface). Not tested in this MR. |
| S-4 | TLS enforced for the collector outside development | TestLoad_UsageData_ValidationRejections/enabled_with_http_collector_url_outside_development, TestLoad_UsageData_HTTPAllowedInDevelopment |
| S-5 | enabled = false guarantees nothing leaves the process |
Config half: TestLoad_UsageData_DisabledSectionLoads, TestLoad_UsageData_AbsentBlockYieldsZeroValue. Tracker no-op: Step 2. |
Notes
internal/config/testdata/usage_data_happy_path.yamlsupports the planned tests; the plan's Step 1Files:entry does not list it explicitly.- ADR-012's collector-endpoint wording ("environment variable") predates the merged spec; handbook amendment: gitlab-com/content-sites/handbook!20410 (merged).
- The first commit is the documented test-first
--no-verifycarve-out; every other commit ran the full hook chain.
Related to #272 (closed)