feat(feedback): disclose session sharing in the /feedback acknowledgement

The /feedback acknowledgement now echoes the receiving session id and
reports the mounted telemetry backend's sharing policy: the telemetry seam
exposes a backend-independent TelemetrySharingStatus through a required
abstract sharing member on the Telemetry service, the OTel backend maps its
mode onto it, and the command appends one policy-only sharing sentence
(full / feedback-only / disabled / not configured) to the acknowledgement.
The web client renders the text through the existing command row without a
client change; a new assembled-browser e2e mounts the shipped telemetry row
in FULL mode against a local dead endpoint and pins the shipped default
sentence as a keyless golden.
This commit is contained in:
Chinesezjc
2026-08-08 02:27:37 +08:00
parent 94abd8631a
commit 3f9d0436eb
28 changed files with 394 additions and 18 deletions
@@ -364,6 +364,31 @@ describe('TelemetryOtel wire', () => {
expect(captures).toEqual([])
})
it('discloses the sharing policy for every mode', async () => {
const { url, captures } = await mockCollector()
const fullCtx = new Context()
await fullCtx.plugin(SessionStore)
const full = await fullCtx.plugin(TelemetryOtel, { exporter: { url } })
expect(fullCtx.telemetry.sharing).toBe('full')
await full.dispose()
const gatedCtx = new Context()
await gatedCtx.plugin(SessionStore)
const gated = await gatedCtx.plugin(TelemetryOtel, { mode: TelemetryMode.FEEDBACK_ONLY, exporter: { url } })
expect(gatedCtx.telemetry.sharing).toBe('feedback-only')
await gated.dispose()
const disabledCtx = new Context()
await disabledCtx.plugin(SessionStore)
const disabled = await disabledCtx.plugin(TelemetryOtel, { mode: TelemetryMode.DISABLED })
expect(disabledCtx.telemetry.sharing).toBe('disabled')
await disabled.dispose()
// No record was emitted by any mode, so nothing reached the collector.
expect(captures).toEqual([])
})
it('defaults direct construction to full delivery', async () => {
const { url, captures } = await mockCollector()
const ctx = new Context()