vantage 0.1.2
vantage: ^0.1.2 copied to clipboard
An in-app QA & developer-tools HUD for Flutter — device simulation, widget inspection, and an extensible plugin architecture for building QA tooling.
Changelog #
0.1.2 #
Documentation only — no code change.
- A proper icon, and a README that actually sells the thing: a scannable feature list instead of a wall of prose. The claims are the same ones the tests back; nothing was added to the list that the package does not do.
- Platform badge now states all six, which
0.1.1earned but never advertised.
0.1.1 #
Two defects found by the first integrator to compose every Vantage package at once. Both were in the host widget; no public symbol changed.
The "you forgot appBuilder" banner could accuse a correctly-wired app #
The check was a single post-frame sample that latched: if Vantage.appBuilder
had not run by the end of the first frame, the banner went up and nothing ever
took it down. An async LocalizationsDelegate is enough to trigger that — until
every delegate resolves, Localizations renders an empty Container, so there is
no Navigator and no MaterialApp.builder on the first frame. vantage_a11y's
VantagePseudoLocalizationDelegate declares Future<T> load(Locale) async, which
can never return a SynchronousFuture, so using vantage_a11y made core accuse
the app of a misconfiguration that did not exist.
- The check is now bound by wall clock (a two-second grace), not by a frame or loop count — an app that renders one frame and then idles produces no further frames to count.
- The diagnostic no longer latches:
appBuildermounting at any later point retracts the banner. - The banner is now wrapped in
IgnorePointer. It is aMaterialpinned across the top of the app whoseTexthit-tests opaquely, so it silently swallowed every tap in that band — the integrator lost app-bar buttons to it. It has nothing to tap, and the same message still goes todebugPrint. - It still fires, unchanged, for an app that genuinely never adds the hook.
Vantage.shellStyle did nothing after the first build #
The HUD shell's onGenerateRoute runs once, so the route's builder closed over
whatever shellStyle existed then. Passing a different style to Vantage later
changed nothing on screen, which made bubble-vs-docked — a headline feature — a
construction-time constant. The one-off quickActions list went stale through the
identical closure and is fixed with it.
Both values now travel down the tree in an inherited widget above the HUD's
Navigator instead of into the closure; the route's overlay entries are ordinary
descendants, so they depend on it and rebuild when it changes. The shell route is
still an OverlayRoute — never a ModalRoute, which would contribute a
full-screen ModalBarrier and make the hosted app uninteractable. The tap-through
and single-ModalBarrier regression tests are unchanged and still pass.
0.1.0 #
Redaction keeps the document parseable — approved api-change, 2026-08-01 #
VantageDefaultRedactor now emits a quoted mask where it replaced a quoted
value, so {"password": "hunter2"} redacts to {"password": "[REDACTED]"}
instead of the unparseable {"password": [REDACTED]}. Every text artifact in a
bug bundle goes through this redactor, so the old behaviour handed a developer a
jsonDecode failure on exactly the artifacts that had carried something
sensitive. No public symbol changed — behaviour only.
- Unquoted values are unchanged: form-encoded bodies, query strings and plain
log lines have no quotes to preserve, so
token=abc&page=2still redacts totoken=[REDACTED]&page=2. Pinned by a test, so the fix cannot over-reach. redact()is still idempotent, and the shared corpus is unaffected — it asserts a secret's absence, never the mask's shape.- This closes the item the entry below recorded as "Known and unchanged".
Redaction — approved api-change, 2026-08-01 #
VantageDefaultRedactor guards every contributor's text artifact on the way
into a bug bundle, and a shared corpus found it leaking 13 credential shapes. All
are now covered. No public symbol changed — behaviour only.
- Keys match separator-insensitively, so
accessToken,access_tokenandaccess-tokenare one rule. Dart JSON is overwhelmingly camelCase, so this was the common case, not an edge case. - New key coverage:
sessionId,cvv,cvc,pin,ssn,creditCard,cardNumber,accountNumber,routingNumber,iban,otp,passphrase,credentials,privateKey, and the usual auth headers (Authentication,X-Csrf-Token,X-Amz-Security-Token,X-Firebase-AppCheckand friends). - New shape coverage, for secrets with no key beside them: JWTs (self-
identifying — the header segment always begins
eyJ), credentials embedded in a URL (https://user:pw@host, masking the whole pair), card numbers written in groups (spaces defeat the plain 13–19 digit rule), and US SSNs. - Fixed: the unquoted-value branch swallowed the closing quote of an enclosing
JSON string literal, so redacting a
key=valueshape inside a literal produced unparseable JSON — on exactly the failed-request payloads a tester files a bug about.
Known and unchanged at the time of this entry — superseded by the entry above,
same day: the mask was emitted unquoted, so masking a quoted JSON value yielded
technically invalid JSON. Still best-effort, not a guarantee — the
class dartdoc states what it does and does not catch, and
vantageRedactionCorpus in vantage_network_core pins both.
Core 1.1 — capability batch #
EventSource+ a host-owned merged, timestamped, ring-buffered event bus (VantageScope.eventBus, default capacity 500). RegisteredEventSourceplugins are relayed automatically and stamped with their pluginid.ExportContributor+ an export pipeline with mandatory redaction of text artifacts (VantageScope.buildExport).VantageSensitivity.sensitiveartifacts are dropped unless explicitly requested; text artifacts always pass throughVantageRedactor; plugin ids and filenames are sanitized to one safe path segment each (no traversal); a throwing contributor is isolated and recorded in the manifest.- Scope is stated in the manifest rather than overclaimed:
redacted: truecovers text only, alongsideredactionScope: 'text-artifacts-only'andunredactedBinaryArtifacts.VantageDefaultRedactoris pattern-based best-effort — a safety net over data the plugin already redacted, never the only line of defence. - Email masking is opt-in (
VantageDefaultRedactor(maskEmails: true)) and the pipeline enables it forVantageSensitivity.sensitiveartifacts only, so an ordinary log keeps the addresses a tester needs. - Breaking (experimental API):
ExportContributor.buildExportnow takes aVantageExportContext. Nothing implemented the mixin before, so no plugin is affected.
- Scope is stated in the manifest rather than overclaimed:
VantageScope.captureApp({pixelRatio})— PNG bytes of the app subtree from a core-ownedRepaintBoundaryplaced above the app and inside the simulation. Returns null (never throws) where rasterization is unavailable, before the first paint, or for apixelRatiooutside(0, 8].- The host now detaches every plugin (
onDetach) whenVantageis disposed, so anEventSource's stream controller is released with its plugin. VantageStorage+VantageMemoryStorage: namespaced, debug-only key-value persistence forString/bool/int/double, inert underkReleaseMode. An invalid namespace throwsArgumentError(not an assert), and views nest (a/b/). Core still depends on the Flutter SDK only; a persistent adapter is a later federated package.VantageScope.appRootElementis now populated by the host (same boundary ascaptureApp). No signature change — the getter existed since 1.0; its doc comment now states exactly which element it is (the boundary wrapping the app, whose single child is the app's own root).- Contract-test kit:
expectVantageEventSourceIsBroadcast,expectVantageExportArtifactsSafe, plus four new tests insiderunVantagePluginContractTests(lifecycle-with-scope, broadcast events, bundle-safe artifacts, export-survives-null-capture). src/api/experimental.dartis now a compatibility re-export ofvantage_event.dart+vantage_export.dart.
Slice 1 #
- Initial repository scaffold: pub workspace + melos, strict lints
(
very_good_analysis), CI (format · analyze · api-guard · test), the frozen-contract guard, and the Slice 1 (core shell + plugin API) design spec. - Core shell:
Vantage+Vantage.appBuilder, controller, registry, scope, activation gesture, bubble + docked shell styles, quick actions, contract kit.