feat(telemetry): record external-datastore-configured flag per invocation#1381
Conversation
…tion Adds `externalDatastoreConfigured` to InvocationContext, true when the repo marker declares a non-`filesystem` datastore (custom providers like S3). The signal is "data lives behind a custom datastore provider," so unset markers and local `filesystem` datastores both report false. Extracted as `isExternalDatastoreConfigured(datastore)` helper alongside buildInvocationContext, with unit coverage for undefined, filesystem, and custom-type cases.
There was a problem hiding this comment.
Code Review
Clean, well-scoped PR that adds a single boolean telemetry signal for whether the repo uses a non-filesystem datastore. The implementation follows established patterns throughout.
Blocking Issues
None.
Suggestions
- The
isExternalDatastoreConfiguredhelper is a pure domain predicate (operates onDatastoreConfigData, no CLI/infra dependencies). It could live closer to the domain — e.g., next toisCustomDatastoreConfiginsrc/domain/datastore/datastore_config.ts— for discoverability and reuse. Not blocking since it's only used at the telemetry-integration boundary today and the placement is consistent with howbuildInvocationContextcomposes other signals.
Looks good — types are consistent across the InvocationContext/InvocationContextData interfaces, the wire-shape contract test locks the new field for the consumer, all three predicate cases (undefined, filesystem, custom) are covered, and the marker.datastore call site types align correctly. No import-boundary or security concerns.
There was a problem hiding this comment.
Adversarial Review
Critical / High
None found.
Medium
- Backward compatibility on deserialization (
src/domain/telemetry/invocation_context.ts:75): WheninvocationContextFromDatais called on JSON written by the previous version (which hasinvocationContextpresent but noexternalDatastoreConfiguredkey),props.externalDatastoreConfiguredisundefinedat runtime despite thebooleantype. The valueundefinedis stored as-is and is falsy, so downstream checks likeif (ctx.externalDatastoreConfigured)work correctly. However, a strict=== falsecomparison would fail. This matches the precedent set byisInteractive(same pattern, no default fallback), and since the field is only consumed server-side via the wire-shape test (which always sendstrue/false), the risk is low. A defensive?? falseincreateInvocationContextwould harden this:externalDatastoreConfigured: props.externalDatastoreConfigured ?? false,
Low
- Empty-string
typefrom malformed YAML (src/cli/telemetry_integration.ts:41): If a.swamp.yamlhasdatastore: { type: "" },isExternalDatastoreConfiguredreturnstruebecause"" !== "filesystem". This is arguably correct (an empty type isn't "filesystem"), but it could produce a misleading telemetry signal. Very unlikely in practice since the marker is normally validated upstream.
Verdict
PASS — Clean, well-tested additive change. The new boolean flag is constructed atomically at the call site, round-trip tested through all persistence layers, and the wire-shape contract test locks the downstream schema. The backward-compat note (Medium #1) is a hardening suggestion, not a blocker — the existing isInteractive field has the same exposure and has shipped without issues.
Summary
externalDatastoreConfigured: booleantoInvocationContext/InvocationContextData, populated at telemetry-service init.typeis notfilesystem— custom providers like S3. Unset markers and localfilesystemdatastores both report false.isExternalDatastoreConfigured(datastore)helper next tobuildInvocationContext, with unit coverage for the three cases.properties.invocationContext.externalDatastoreConfigured—http_telemetry_sender_testlocks the contract so the swamp-club consumer can query it without a server-side change.Test Plan
deno fmt --checkdeno lintdeno checkdeno run test src/domain/telemetry/... src/cli/telemetry_integration_test.ts src/infrastructure/persistence/json_telemetry_repository_test.ts src/infrastructure/telemetry/http_telemetry_sender_test.ts— 102 passed