Skip to content

0.0.9

Choose a tag to compare

@github-actions github-actions released this 29 Sep 17:58
· 2 commits to master since this release
2c99da3

Added

  • A monotonic clock, an interaction link, and exclusive self time land on every telescope record. HttpRequestRecord, QueryRecord, EventRecord, MagicModelRecord, MagicCacheRecord and FramePerfRecord all gain atUs (an int? atUs constructor param stored as atUs ?? FlutterTimeline.now, comparable across record types regardless of wall-clock skew), interactionId (String?) and linkedBy (String?, one of zone / frame / window), all three serialized in toJson. HttpRequestRecord additionally carries requestId, startUs and endUs for exact request/response pairing. FramePerfRecord gains vsyncStartUs from FrameTiming.timestampInMicroseconds(FramePhase.vsyncStart); its doc comment marks clock parity with atUs as needing live validation, since the engine documents that timestamp only as microseconds "from some epoch" and a widget test can only inject synthetic FrameTiming values, never a real engine-reported one. Every block in a FramePerfRecord.blocks map gains selfMicros: FramePerfWatcher's drain now computes each block's exclusive duration from AggregatedTimings.timedBlocks start/end nesting (a stack walk over blocks sorted by start, tie-broken by the longer block first) and subtracts directly nested children from the existing inclusive micros. telescope:frames and telescope:requests print the new fields, linkedBy on its own when there is no interactionId (the window case). Every new constructor parameter is optional or defaulted, so a constructor call that does not pass blocks by an explicit record type keeps compiling (magic_devtools/lib/src/telescope_integration.dart does); the blocks type is the one exception, below. The skill's records.md, mcp-tools.md and cli-commands.md document every new key. (lib/src/records/*.dart, lib/src/watchers/frame_perf_watcher.dart, lib/src/commands/telescope_{frames,requests}_command.dart, skills/fluttersdk-telescope/references/)

  • TelescopeRedaction, the credential lists behind the HTTP buffer, and HttpRequestRecord.copyWith. hideRequestHeaders, hideRequestParameters and hideResponseParameters add names to the defaults (Laravel Telescope merges the same way, it never replaces), hiddenRequestHeaders / hiddenRequestParameters / hiddenResponseParameters read the lowercased lists, redactParameters(data, keys) returns a copy of a Map/List structure with every value under a matching key, at any depth, replaced by mask ('********'), never mutating its input, and redactBody(body, keys) does the same for a JSON string, or pair by pair for a form-encoded one. An adapter calls one of them before it stringifies or truncates a body, since neither a Map.toString() nor a cut JSON string parses, and the store cannot mask what it cannot parse. copyWith replaces requestHeaders, requestBody and responseBody and keeps every other field, atUs included. (lib/src/telescope_redaction.dart, lib/src/internal/redaction_lists.dart, lib/src/records/http_request_record.dart)

Changed

  • BREAKING: FramePerfRecord.blocks is Map<String, ({int micros, int selfMicros, int count})>. It was Map<String, ({int micros, int count})>, and Dart record types with different fields are not assignable to each other, so code that builds a FramePerfRecord from a map of the old record type, or declares a variable of the old type from record.blocks, stops compiling. Add selfMicros to the record literal (the inclusive micros is a safe value when the nesting is unknown) or let the type be inferred. The JSON shape only gains a key, so a reader of ext.telescope.frames output is unaffected. (lib/src/records/frame_perf_record.dart)

  • The artisan floor names this batch's release. fluttersdk_artisan moves ^0.0.16 to ^0.0.17. The old range already admitted 0.0.17, so a fresh pub get resolves nothing differently; what changes is that the floor names the release this package is verified against. artisan 0.0.17 changes stop, restart and a failed start --cdp-port to reap the app's whole process group, and telescope calls none of those APIs. (pubspec.yaml)

Security

  • The HTTP buffer no longer stores credentials verbatim. It is served to AI agents over ext.telescope.requests and MCP, and a Magic app's bearer header, a login body's password and a login answer's Sanctum token all landed in it as sent. TelescopeStore.recordHttp now masks, before buffering and before emitting on onHttpRecord: the value of every request header named authorization, proxy-authorization, cookie, set-cookie or x-api-key, and, in a body that parses as a JSON object or array or reads as form-encoded (grant_type=password&password=..., where only the matching pair's value changes, and a bracketed key such as user[password] or codes[] matches on its last part, as a nested JSON key does), the value under password, password_confirmation, current_password, new_password, token, access_token, refresh_token, secret, client_secret, authorization_code, id_token, two_factor_token or recovery_code (request) and token, access_token, refresh_token, plain_text_token, secret, client_secret, id_token, two_factor_token, recovery_codes, qr_url or qr_svg (response), at any depth. qr_url and qr_svg are on the list because both carry the TOTP secret that secret masks. Names match case-insensitively. An empty value (null, false, '', [], {}) stays visible, a subtree deeper than 64 levels is masked whole so a pathological body cannot overflow the stack, any other body (plain text, a truncated snippet) is kept as given, and a JSON body with nothing to hide keeps its exact bytes. (lib/src/telescope_store.dart, lib/src/telescope_redaction.dart)