kylon-cli 0.4.1-next.751 → 0.4.1-next.753

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -539,78 +539,71 @@ instead of waiting out inactivity timeouts and heartbeat intervals.
539
539
 
540
540
  ## Remote diagnostics
541
541
 
542
- The CLI sends selected structured lifecycle events to the same API-to-Grafana
543
- Loki pipeline as web/mobile (`POST /client-logs/cli`, `service=cli-client`,
544
- `client_kind=cli`). This is event logging, not OpenTelemetry/Tempo tracing.
545
- It uses the credential selected by the running command or computer daemon;
546
- it never ships Grafana credentials or falls back to another saved identity.
547
- Status (`status`/`auth status`, `gateway status`), `diagnose`, and upgrade commands
548
- (`upgrade`, `provider update`, `gateway service`) use a fixed unauthenticated
549
- diagnostic path on the same URL. Login failures use that path too; successful
550
- login selects its issued credential. Other commands never fall back to anonymous
551
- submission when authentication fails. The anonymous handler reuses support-report
552
- IP resolution/rate-limiting but has a separate quota and never creates support
553
- reports or uploads diagnostic bundles.
554
-
555
- Telemetry initialization calls the existing installation store's `ensure()`:
556
- `install.json` in the CLI configuration directory contains the random `installId`,
557
- which is included as `install_id` on both authenticated and anonymous records.
558
- It is created before login and reused across runs. Deleting the file resets it;
559
- copying the configuration can duplicate it. It identifies an installation, not
560
- a physical device or authenticated person. With a stable identifier these are
561
- pseudonymous diagnostics, not unlinkable anonymous data. No hardware fingerprint
562
- is collected. If the installation cannot be read/created, telemetry stays off.
563
- Opt-out is checked before initializing the installation for telemetry.
564
-
565
- Set `KYLON_TELEMETRY_DISABLED=1` in the CLI/daemon process environment to disable
566
- remote diagnostics; local diagnostic logs are unchanged. Restart an already
567
- running daemon after changing its environment. This optional client-only switch
568
- does not require any server/Doppler configuration.
569
-
570
- Only events and fields listed in `@p2/types/cli-telemetry` are accepted on both
571
- ends. Metadata includes CLI version (`app_version`), OS, architecture, client
572
- timestamp, operation ID, existing task/request IDs, durations and error codes.
573
- Raw argv, URLs, paths, hostname, prompts, provider output and credentials are
574
- not uploaded. Identity/workspace attribution comes from server authentication,
575
- not client fields. These are untrusted diagnostics, not an audit log.
576
-
577
- The queue holds at most 100 records, sends at most 20 every five seconds, and
578
- drops failed batches without retrying. Requests have an 800 ms timeout and do
579
- not follow redirects. Normal command completion flushes the latest batch;
580
- shutdown can wait for an in-flight request and one final request (up to roughly
581
- 1.6 seconds). Hard kills and immediate `process.exit()` paths can lose events.
582
- The API limits each authenticated identity to 60 batches/minute and 32 KiB/batch.
583
- Anonymous diagnostics are limited separately to 20 batches/minute per source IP
584
- (hashed for the rate-limit key), with the same size cap. Only command lifecycle
585
- events and a narrower metadata allowlist are accepted; task/workspace/user IDs,
586
- arbitrary error text and request IDs are dropped. The installation ID is supplied
587
- by the client and is not an authentication or rate-limit credential. Existing
588
- infrastructure request logs may retain network metadata; this change does not
589
- introduce or alter a retention policy.
542
+ The CLI reports to the server through one channel (`src/lib/telemetry.ts`):
543
+ every logger record passes through it after redaction, and what leaves the
544
+ machine depends on the identity the running operation selected. This is event
545
+ logging into the API-to-Grafana Loki pipeline (`service=cli-client`), not
546
+ OpenTelemetry/Tempo tracing. It never ships Grafana credentials and never falls
547
+ back to another saved identity.
548
+
549
+ - **Machine identity** (the computer daemon and its supervisor, locked by the
550
+ computer session): posts to `POST /workspaces/:ws/computers/:id/client-events`
551
+ every `warn`/`error` record, the info-level names on the shared inventory, and
552
+ the daemon lifecycle events (`daemon.started`, `daemon.crash_detected`,
553
+ `daemon.system_wake`, `daemon.shutdown`). Fields are flattened one level and
554
+ bounded (32 keys, 300 characters); a prose message is normalized to a
555
+ snake_case name with the wording kept in `text`. The server stamps
556
+ `p2EventType=cli_daemon_event` and the machine's CLI version and OS, holds
557
+ each machine to 300 events per 5 minutes, and announces what it dropped or
558
+ rejected. The operator's `remoteDiagnostics` gateway setting is the consent
559
+ for this path, read at every flush.
560
+ - **User identity** (any other command once it has a credential): posts to
561
+ `POST /client-logs/cli` under the event and field allowlists in
562
+ `@p2/types/cli-telemetry`, so a command never uploads paths, prompts, argv,
563
+ or arbitrary error text. Identity and workspace attribution come from server
564
+ authentication, not client fields.
565
+ - **Anonymous** (status (`status`/`auth status`, `gateway status`), `diagnose`,
566
+ the upgrade commands (`upgrade`, `provider update`, `gateway service`)): the
567
+ same URL without a credential, command outcomes only, with an even narrower
568
+ metadata allowlist. The setup commands (`auth login`, `agent link`, `connect`,
569
+ `onboard`) report anonymously only when they fail, with the setup session id
570
+ from the link inspection and the stage they reached, and switch to the
571
+ credential they obtain. Other commands never fall back to anonymous
572
+ submission when authentication fails.
573
+
574
+ Telemetry initialization calls the installation store's `ensure()`:
575
+ `install.json` in the CLI configuration directory holds the random `installId`,
576
+ sent as `install_id` on every record. It is created before login and reused
577
+ across runs; deleting the file resets it, copying the configuration can
578
+ duplicate it. It identifies an installation, not a device or a person, so these
579
+ are pseudonymous diagnostics. If the installation cannot be read or created,
580
+ telemetry stays off.
581
+
582
+ Set `KYLON_TELEMETRY_DISABLED=1` in the CLI/daemon process environment to turn
583
+ the whole channel off; local diagnostic logs are unchanged. Restart a running
584
+ daemon after changing its environment.
585
+
586
+ Delivery: a bounded queue of 200 records (oldest dropped first, the count
587
+ announced as `gateway.remote_events.dropped_locally`), one batch of up to 20
588
+ every five seconds, plus an immediate flush for the daemon lifecycle events. A
589
+ `401`, `403`, or `404` stops the channel for the rest of the process; any other
590
+ failure keeps the batch and backs off, doubling from 30 seconds to 5 minutes.
591
+ Requests do not follow redirects; a command's request is cut after 800 ms, the
592
+ daemon's after 5 seconds. Normal command completion flushes the latest batch;
593
+ hard kills can lose events. The API limits each user identity to 60 batches per
594
+ minute and 32 KiB per batch, anonymous sources to 20 batches per minute per
595
+ hashed IP.
590
596
 
591
597
  ### Event inventory
592
598
 
593
- This change adds **5 event names at 6 logging call sites**:
594
-
595
- - `cli.command.started`
596
- - `cli.command.completed` (includes nonzero `process.exitCode` outcomes)
597
- - `cli.api.failed` (network exception and HTTP failure call sites)
598
- - `computer.connection.opened`
599
- - `computer.connection.closed`
600
-
601
- It also forwards **25 existing event names**, covering command failure,
602
- gateway connection failures/reconnect scheduling, assignment receipt/acceptance,
603
- provider execution, cancellation, result delivery/outbox replay, supervisor
604
- lifecycle and upgrade outcomes. The shared allowlist is the exact inventory.
605
- Unexpected command exceptions now reuse `cli.command_failed` instead of an
606
- unstructured event name. Workspace API failures are captured in the shared
607
- workspace client; other HTTP clients retain their existing selected diagnostics.
608
- Successful HTTP requests are not uploaded in this first version.
609
-
610
- Validation extends the existing logger and API route tests, plus the real
611
- credential/middleware integration test for CLI/computer keys and forbidden
612
- sibling/read routes. Live customer-machine-to-Grafana verification is still
613
- required after deployment; these tests do not prove Grafana delivery.
599
+ Info-level names are the shared inventory in `@p2/types/cli-telemetry`:
600
+ command lifecycle (`cli.command.started`, `cli.command.completed`,
601
+ `cli.command_failed`, `cli.api.failed`), connection open/close, gateway
602
+ connection failures and reconnect scheduling, assignment receipt and
603
+ acceptance, provider execution, cancellation, result delivery and outbox
604
+ replay, supervisor lifecycle, and upgrade outcomes. A machine identity adds
605
+ every warn/error record and the daemon lifecycle; a user identity is limited to
606
+ the inventory on both ends.
614
607
 
615
608
  ## State Model
616
609
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.4.1-next.751",
3
- "fingerprint": "90173f552d94066c20203c6eed919ff58f5c14a0a85235114036aa3ed3996054",
4
- "source_commit": "b01e85c9720cc5d32ccdb84f6e00d4cd4aba89df"
2
+ "version": "0.4.1-next.753",
3
+ "fingerprint": "7760d3eeb79fe68bca181900357f57ea9140747350e96d3b2c5e3d9aa4a37900",
4
+ "source_commit": "97b6dbbefb15e1787da6d45fe5ea4cfb6a4ffb5e"
5
5
  }