Skip to content

feat(telemetry): Tier-2 opt-in fleet sharing — consent + egress + backfill (ent#12) - #1723

Merged
vybe merged 2 commits into
devfrom
feature/ent12-telemetry-sharing
Jul 23, 2026
Merged

feat(telemetry): Tier-2 opt-in fleet sharing — consent + egress + backfill (ent#12)#1723
vybe merged 2 commits into
devfrom
feature/ent12-telemetry-sharing

Conversation

@dolho

@dolho dolho commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

ent#12 — Tier-2 opt-in fleet sharing (OSS consent + egress + backfill)

The opt-in egress layer on top of Tier-1 (ent#184). Default-OFF, reversible. Gating shape confirmed: OSS-core consent+egress+backfill, enterprise-gated benchmark carrot.

⚠️ Stacked on #1721 (ent#184). Base is the ent#184 branch so this diff shows only Tier-2 — retarget to dev when #1721 merges.

Never egresses without consent — two independent gates

Both re-checked in share_now: the stored telemetry_sharing_enabled consent (default-off) AND the config switch TELEMETRY_SHARING_ENABLED (honors DO_NOT_TRACK). Either off ⇒ nothing leaves the box.

What ships

  • services/telemetry_sharing_service.py — consent state, build_aggregate_payload (anonymized: install id + version/edition/platform/python + coarse enterprise_features + agent/execution counts + Tier-1 funnel counts; no PII, content, prompts, emails, agent names), share_now (gated, fail-open, honest 2xx), and a sleeps-first jittered heartbeat (default 24h). Reuses the operator-intake Task Actions UI #38 credential-free transport.
  • Retroactive backfill at consent — on off→on, an immediate fire-and-forget backfill over a disclosed window (default 30d) from Tier-1 product_events.
  • APIGET /api/settings/telemetry-sharing (status + inspectable payload_preview — see exactly what would be sent before consenting) + PUT (admin + human-only, audit-logged, 409 when hard-disabled). feature-flags exposes telemetry_sharing_enabled.
  • Frontend — value-framed optional non-blocking wizard ask (hidden when hard-disabled) + reversible default-off Settings → General panel with payload preview + backfill picker; the gated funnel panel shows the benchmark status.
  • Docsdocs/PRODUCT_EVENTS.md Tier-2 section (schema + reversibility + backfill) + requirements §45.1.

AC coverage

  • Consent surface in wizard (value-framed) + Settings toggle (default-off, reversible), each stating what's shared
  • On consent: optional retroactive backfill, disclosed explicitly
  • Anonymized aggregate payload (documented schema, no PII) on a periodic heartbeat
  • Opt-out stops egress immediately; docs cover schema + reversibility
  • v1 carrot: participants view a benchmark status keyed by installation_id (gated view lands with the enterprise PR; hosted percentile service is its own issue)
  • Hosted aggregation intake scoped out (separate issue)

Verification

tests/unit/test_ent12_telemetry_sharing.py (8): no-PII payload, both-gate egress, opt-out stops egress, fail-open, non-2xx not marked shared, consent round-trip. Live on the Postgres stack: gating + delivery to a local sink + no-PII + reversibility (21 checks) + router/preview end-to-end. No real external egress in any test.

Related to ent#12 · Tier-1 ent#184 · pairs with trinity-enterprise feature/12-telemetry-benchmark

🤖 Generated with Claude Code

@vybe
vybe changed the base branch from feature/ent184-product-events-capture to dev July 22, 2026 08:37
…kfill (ent#12)

The opt-IN egress layer on top of Tier-1 (ent#184). Default-OFF, reversible.
Gating shape confirmed: OSS-core consent+egress+backfill, enterprise-gated
benchmark carrot (the reward). Stacked on the ent#184 OSS branch.

Never egresses without consent — TWO independent gates, both re-checked in
share_now: the stored `telemetry_sharing_enabled` consent (default-off) AND the
config switch `TELEMETRY_SHARING_ENABLED` (honors DO_NOT_TRACK). Either off ⇒
nothing leaves the box.

- services/telemetry_sharing_service.py: consent state (system_settings),
  build_aggregate_payload (anonymized — installation_id + version/edition/
  platform/python + coarse enterprise_features + agent/execution COUNTS + Tier-1
  activation-funnel counts; NO PII, content, prompts, emails, or agent names),
  share_now (gated, fail-open, honest 2xx), and a sleeps-first jittered heartbeat
  (default 24h) that shares when consent is on. Reuses the operator-intake #38
  credential-free httpx transport.
- Consent-time retroactive backfill: on the off→on transition the router
  schedules an immediate fire-and-forget backfill over a disclosed window
  (default 30d) sourced from Tier-1 product_events.
- API (routers/settings.py): GET /api/settings/telemetry-sharing (status +
  inspectable payload_preview — the operator sees EXACTLY what would be sent
  before consenting) + PUT (admin + human-only, audit-logged, 409 when hard-
  disabled). feature-flags exposes telemetry_sharing_enabled (observability).
- config.py: TELEMETRY_SHARING_ENABLED/URL/INTERVAL_HOURS/BACKFILL_DEFAULT_DAYS.
- lifespan: staggered heartbeat start (+9s).
- Frontend: value-framed, optional, non-blocking consent ask in the onboarding
  wizard (hidden when hard-disabled) + a reversible default-off Settings → General
  panel (TelemetrySharingPanel.vue) with the inspectable payload preview + backfill
  picker; the gated ActivationFunnelPanel shows the benchmark reciprocity status.
- Docs: docs/PRODUCT_EVENTS.md Tier-2 section (payload schema + reversibility +
  backfill) + requirements §45.1.

Tests: tests/unit/test_ent12_telemetry_sharing.py (8) — no-PII payload, both-gate
egress, opt-out stops egress, fail-open, non-2xx not marked shared, consent
round-trip. Verified live on the Postgres stack: gating + delivery to a local
sink + no-PII + reversibility (21 checks), and the router/preview end-to-end. No
real external egress in any test.

Related to ent#184 (Tier-1) · pairs with trinity-enterprise benchmark carrot.
Depends on #1721 (ent#184 OSS) — rebase onto dev when it merges.

Related to ent#12
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vybe
vybe force-pushed the feature/ent12-telemetry-sharing branch from f087c16 to 9e5f48d Compare July 22, 2026 08:40
@github-actions

Copy link
Copy Markdown

⚠️ Nightly unit-suite check skipped — merge conflict against dev.

Resolve by running git merge dev locally and pushing the result. The next nightly run will re-test once the conflict is gone.

…-all block, wizard disclosure (ent#12)

Validation-pass fixes on the Tier-2 sharing PR:
- AuditEventType.SETTINGS does not exist — the consent audit call raised
  AttributeError into the best-effort except and never logged. Use
  CONFIGURATION like every sibling settings audit.
- Wire TELEMETRY_SHARING_{ENABLED,URL,INTERVAL_HOURS,BACKFILL_DEFAULT_DAYS}
  into both compose backend.environment blocks + .env.example — the documented
  hard kill switch was inert in every containerized deploy (#1056 class).
- Block the telemetry_sharing_* key family in the generic settings PUT — the
  dedicated route's human-only gate (reject_agent_principal + 409 + audit) was
  bypassable by an admin-owned agent-scoped key (trinity-ops-agent#232 class).
- Wizard consent copy now discloses the 30-day backfill (FR-4).

Two regression tests pin the enum and the blocklist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated via subagent review: payload is genuinely anonymized (allowlist-filtered, no PII), double gate re-checked at send time, opt-out immediate. Three criticals fixed on the branch (nonexistent audit enum, dead TELEMETRY_SHARING_* compose wiring, generic-PUT consent bypass) + wizard backfill disclosure — all with regression tests, CI green. Residual: per-worker heartbeat dup under --workers 2 (dedupe on installation_id server-side) — follow-up.

@vybe
vybe merged commit 7508fc5 into dev Jul 23, 2026
24 checks passed
vybe pushed a commit that referenced this pull request Jul 23, 2026
80b1bd7 was stale — it predated the ent#189 telemetry merge (3926e63), so the
pin was missing the enterprise half of the #1723 OSS pair. 594b0af additionally
carries ent#217 (portal thread titles on subscription OAuth), closing the
ent#186 known-limitation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
vybe pushed a commit that referenced this pull request Jul 23, 2026
…ed to 594b0af

Recheck findings: #1723 merged (ordering gate cleared); the #1753 pin at
80b1bd7 was stale (missing the ent#189 telemetry merge — the ent#185 class its
own checklist warns about) — re-pointed to 594b0af; new PR ent#217 validated
and merged, completing the ent#186 portal-titles feature and removing its
Known-limitations line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
vybe added a commit that referenced this pull request Jul 23, 2026
…1753)

* chore(enterprise): bump submodule to enterprise-main tip for 0.8.5

Picks up the 0.8.5 enterprise payload: skill-runner module (ent#139 + review
fixes: single-slot pin), shared-sessions rooms (ent#169 + enumeration-oracle
fix), module-registration isolation (ent#196), portal per-user memory
(ent#212), telemetry benchmark surface (ent#12), eval strategy doc (ent#206).

Pointer verified at enterprise-main TIP (80b1bd7) per the release rule — a
stale pin ships 403s with green CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(enterprise): re-point bump to new enterprise-main tip 594b0af

80b1bd7 was stale — it predated the ent#189 telemetry merge (3926e63), so the
pin was missing the enterprise half of the #1723 OSS pair. 594b0af additionally
carries ent#217 (portal thread titles on subscription OAuth), closing the
ent#186 known-limitation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Eugene Vyborov <eugene@beingluminous.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@vybe vybe mentioned this pull request Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants