aibridgejs Changelog
[Unreleased]
Section titled “[Unreleased]”[0.5.5] - 2026-06-08
Section titled “[0.5.5] - 2026-06-08”Changed
Section titled “Changed”- Project home migrated to the
isluminaGitHub org; the package is now published from there via npm trusted publisher (OIDC + SLSA provenance). Family-wide version alignment at0.5.5— no runtime or API changes.
[0.5.2] - 2026-06-05
Section titled “[0.5.2] - 2026-06-05”- Review-driven documentation fix (
llms-full.txt; plus repo-onlyCONTRIBUTING.md): clarity from a cross-package code review. No runtime or API change;distbyte-identical to 0.5.1.
[0.5.1] - 2026-06-02
Section titled “[0.5.1] - 2026-06-02”-
Response branch guarded against throwing getters on
error.message/error.code(src/bridge.ts): the error-coercion block in the"response"switch case is now wrapped intry/catch. A hostile or buggy host that supplies an error object with a throwing getter previously caused the exception to escape the adapter callback, leaving the call promise pending indefinitely (hanging past its own timeout). The guard catches any such throw and falls back to the same safe defaults ("Remote error"/"REMOTE_ERROR") already used for missing or non-string fields. Well-formed error shapes are unaffected. Regression test added (A9cintest/bridge.test.ts). -
iframe
expectedSourcenull/fallback branches now covered by tests (test/iframe.test.ts): three cases that were previously exercised only implicitly are now tested explicitly: (a)expectedSource: nullpassed directly enables origin-only acceptance; (b) when nopostTargetcan be inferred,expectedSourcedefaults tonull(origin-only fallback — the security-relevant default-derivation branch); (c) a message from the correct origin but a mismatchedevent.sourceunder the default parent-inferred config is rejected.
Recommended CI follow-up (not included — requires workflows permission)
Section titled “Recommended CI follow-up (not included — requires workflows permission)”-
Add a
verify:llmsstep to .github/workflows/ci.yml (theverify:llmsscript exists and passes locally) so CI guardsllms-full.txtfreshness, matching all six sibling repos. -
Rename the test step
"Test with coverage thresholds"→"Test (with coverage thresholds)"to match the sibling-repo form.These two
.github/workflows/ci.ymledits are intentionally omitted from this branch because the automation pushing it lacks the GitHubworkflowspermission; a maintainer should apply them directly.
Changed (docs)
Section titled “Changed (docs)”createIframeAdapterJSDoc clarifiesexpectedSourcecontract (src/iframe/index.ts): documents that omittingpostTargetwhen no target can be inferred yieldsexpectedSource: null(origin-only validation, source check disabled); that exact-origin allowlisting is the primary security gate; and that theevent.sourcecheck is defense-in-depth. No behavior change.
[0.4.1] - 2026-05-29
Section titled “[0.4.1] - 2026-05-29”Consistency patch — CI workflow and documentation hygiene. No runtime API
change; dist/ is byte-identical to 0.4.0.
Changed (CI)
Section titled “Changed (CI)”publish.ymlnow passes--provenance --access publicexplicitly (.github/workflows/publish.yml), matching the rest of the ai*js family. This makes intent explicit rather than fixing a behaviour gap: 0.4.0 was already published with SLSA provenance (npm OIDC Trusted Publishing enables it automatically) and--access publicis the default for this unscoped package. The explicit flags keep the workflow consistent with its siblings and robust if npm’s defaults change.
Removed (repo-only; not shipped in the npm tarball)
Section titled “Removed (repo-only; not shipped in the npm tarball)”STABILITY_ZHTW.md: the Traditional-Chinese mirror of the stability contract is removed to match the family convention — the EnglishSTABILITY.mdis the single source. The language-switcher line atopSTABILITY.mdis removed with it, andREADME_ZHTW.md’s stability link now points toSTABILITY.md.
Compatibility
Section titled “Compatibility”Non-breaking: no new exports, no removed exports, no signature changes.
dist/ bundles are byte-identical to 0.4.0; the published tarball differs only
in README_ZHTW.md (one documentation link) and llms-full.txt (regenerated
from the trimmed STABILITY.md and this changelog).
[0.4.0] - 2026-05-29
Section titled “[0.4.0] - 2026-05-29”Dependency-hygiene milestone and 1.0-track stability freeze. No runtime API addition; the production bundle is byte-identical to 0.3.2.
Changed (stability)
Section titled “Changed (stability)”- 0.3.x public surface declared frozen for the 1.0 track
(STABILITY.md,
STABILITY_ZHTW.md): everystableexport — corecreateBridge, the five error classes, and all four adapter / detect entrypoints with their types — is now committed to additive-only evolution until 1.0. The twoexperimentaldesign-note items (binary envelope, streaming RPC) are explicitly excluded and remain targeted no earlier than v0.7.
Dependency hygiene (dev-only; not shipped in the npm tarball)
Section titled “Dependency hygiene (dev-only; not shipped in the npm tarball)”- Verified minimal; no reduction available. Zero runtime
dependenciesand zeropeerDependencies(unchanged since 0.1.0). The nine devDependencies are already aligned to the ai*js family-canonical versions;depcheckreports no unused or missing dependency,pnpm auditreports no known vulnerability at moderate or above, andpnpm dedupe --checkfinds no deduplication opportunity. CI workflow actions are pinned to the current@v6majors (actions/checkout,actions/setup-node,pnpm/action-setup). This release records the audited-clean baseline rather than changing it.
Compatibility
Section titled “Compatibility”Non-breaking: no new exports, no removed exports, no signature changes, no
default-behaviour change. A version-line unification (aligning aibridgejs with
the ai*js family’s 0.4.0) plus a documentation-level stability commitment.
dist/ bundles are byte-identical to 0.3.2; only llms-full.txt changes,
reflecting the updated STABILITY.md and CHANGELOG.md it embeds.
[0.3.2] - 2026-05-29
Section titled “[0.3.2] - 2026-05-29”Findings from a second independent Codex review pass.
Fixed (resource leaks)
Section titled “Fixed (resource leaks)”- Adapter
dispose()invokes each subscription’s unsubscribe (src/mock/index.ts, src/iframe/index.ts, src/flutter/index.ts):dispose()previously called onlysubscribers.clear(), leaving any"abort"listener registered on an externally-suppliedAbortSignalorphaned until that signal eventually fires. Each adapter now maintains asubCleanupsregistry and iterates it indispose(), completing the 0.3.1subscribe()unsubscribe cleanup so a disposed adapter fully releases listeners held on external signals.
Fixed (docs)
Section titled “Fixed (docs)”- Completed
event.sourceopt-out wording in Security tables (README.md, README_ZHTW.md, llms.txt): the 0.3.1 fix updatedSTABILITY.mdand prose sections but missed the iframe Security tables and thellms.txtindex sentence. Wording now consistently reflects that source-checking can be disabled withexpectedSource: null. - Corrected Vitest example from
environment: 'jsdom'to'node'(README.md, README_ZHTW.md):jsdomwas removed as a devDependency in 0.3.1; the example config now matches the actual test environment. - Removed an unimplemented
BridgeDisposedErrortrigger from the error table (README.md, README_ZHTW.md): the table claimed the iframe adapter raises it when it “detects its target window vanished” — no such detection exists; the adapter raisesBridgeDisposedErroronly on explicitdispose(). - Qualified the
AbortSignalclaim inllms.txt:ready()andcall()accept anAbortSignal;emit()is fire-and-forget and takes none. The previous “all async methods” wording overstated the surface.
Compatibility
Section titled “Compatibility”Non-breaking; no API change. The leak fix only affects the dispose path for subscriptions made with an external AbortSignal.
[0.3.1] - 2026-05-29
Section titled “[0.3.1] - 2026-05-29”All five findings below originated from an independent Codex review of the 0.3.0 runtime. None are breaking.
Fixed (correctness)
Section titled “Fixed (correctness)”createBridgecoerces malformed remote-error fields (src/bridge.ts): aresponseenvelope with a non-stringerror.code/error.messagecould surface a non-string onBridgeRemoteError, whosecode/messageare typedstring. The bridge now falls back to"REMOTE_ERROR"/"Remote error"when a field is missing or the wrong type, so a malformed host cannot violate the error type contract. Well-formed string errors are unchanged.
Fixed (resource leaks)
Section titled “Fixed (resource leaks)”ready()detaches its dispose listener on every settle path (src/bridge.ts): repeatedreset()against a hungadapter.ready()previously left one orphaned"abort"listener per round on the internal signal untildispose(). The reset path now removes the round’s listener. No behavioural change — the identity guard already prevented double-settle.- Adapter
subscribe()unsubscribe detaches its signal listener (src/mock/index.ts, src/iframe/index.ts, src/flutter/index.ts): the returned unsubscribe now callssignal.removeEventListener("abort", ...), mirroringbridge.on(). Manual unsubscribe with a long-livedAbortSignalno longer accumulates listeners.
Fixed (docs)
Section titled “Fixed (docs)”- iframe
event.sourcevalidation documented as opt-out, not absolute (README.md, README_ZHTW.md, STABILITY.md,STABILITY_ZHTW.md): the docs claimedevent.sourceis validated on every inbound message; source-checking can in fact be disabled withexpectedSource: null(intentional since 0.1.3). Wording now matches the contract. - Removed stale
'cocos'from the documentedplatform()union (README.md, README_ZHTW.md, llms.txt): the literal was dropped fromBridgePlatformin 0.1.3 but lingered in the API docs. Now'iframe' | 'flutter' | 'mock' | 'unknown', matchingsrc/types.ts.
Internal (not shipped in the npm tarball)
Section titled “Internal (not shipped in the npm tarball)”- Test-suite hardening: dropped the unused
jsdomdevDependency (tests run on thenodeenvironment), added afast-checkproperty test for request/response id-correlation under arbitrary response ordering, and added aready()mid-flight abort test plus regression tests for the fixes above. 112 tests; coverage 97.88 / 91.86 / 100 / 100.
Compatibility
Section titled “Compatibility”Non-breaking: no new exports, no removed exports, no signature changes. The remote-error coercion and listener-cleanup fixes only alter behaviour for malformed input or pathological reset/churn scenarios; well-formed usage is unchanged. All subpath bundles stay within their gzip budgets.
[0.3.0] - 2026-05-29
Section titled “[0.3.0] - 2026-05-29”Added (docs)
Section titled “Added (docs)”STABILITY.md+STABILITY_ZHTW.md: per-export stability contract and per-subpath pure-web safety labels. Each subpath now carries one of four tags:pure-web safe,pure-web safe (auto-fallback),requires native shell,dev only. Consumers no longer need to read adapter source to judge whether a subpath is safe to import in a pure-web page (no iframe parent, no native shell). The contract also lodges placeholder design notes for the two long-running [draft] limitations (binary envelope, streaming RPC) so they have a stable URL before any implementation lands.
Changed (docs)
Section titled “Changed (docs)”README.md+README_ZHTW.mdsubpath table and each adapter section now carry pure-web safety annotations and link toSTABILITY.mdfor the full contract.- JSDoc on
createMockAdapter/createIframeAdapter/createFlutterAdapter/detectBridgeAdapter: each factory now opens with a one-line pure-web safety statement plus a link toSTABILITY.md. No signature changes.
Changed (tooling)
Section titled “Changed (tooling)”scripts/build-llms-full.mjsnow includesSTABILITY.mdin the concatenatedllms-full.txt, so LLM-facing context exposes the stability contract in the same fetch. Source documents in order:README.md→STABILITY.md→CHANGELOG.md→CONTRIBUTING.md.
Compatibility
Section titled “Compatibility”This release is runtime-identical to 0.2.1. No new exports, no removed exports, no signature changes. Bundle gzip stays well within budget for every subpath (measured at index 2351 / mock 753 / iframe 1161 / flutter 1243 / detect 1900 B; budgets unchanged). Coverage maintained at 97.86 / 91.38 / 100 / 100.
[0.2.1] - 2026-05-28
Section titled “[0.2.1] - 2026-05-28”Changed (CI)
Section titled “Changed (CI)”publish.ymlnow triggers onpush: tags: ["v*"]instead ofrelease: published. Aligns with the trigger used byaifsmjsandaiecsjsin the same ai*js family. Prior to this, a manualgh release create vX.Y.Zwas required after every tag push to fire the publish workflow.publish.ymlnow runsverify:llmsin the gate chain (was already inprepublishOnlyvia the new 0.2.0 script, but now also visible as a CI step for faster failure attribution).
Changed (docs)
Section titled “Changed (docs)”- README opening unified across the ai*js family: five-badge shields row (npm + CI + License + AI Generated + 繁體中文/English), one-line tagline as blockquote, ecosystem footer linking to the other two packages. Same shape in
README.mdandREADME_ZHTW.md.
[0.2.0] - 2026-05-28
Section titled “[0.2.0] - 2026-05-28”Fixed (correctness)
Section titled “Fixed (correctness)”reset()settles ready waiters parked on a slowadapter.ready()(src/bridge.ts): previouslyreset()cleared only thependingmap (entries written after ready resolved). Calls awaiting a slow / hungadapter.ready()never reachedpendingand stayed parked indefinitely past reset. The cachedreadyPromise’s rejecter is now captured and invoked fromreset(), so in-flightcall()/ready()waiters surface aBridgeResetErrorsynchronously. The captured rejecter uses an identity guard before clearing the module-level slot, so a staleadapter.ready()resolution arriving AFTER reset cannot clobber the new round’s reject handle (regression caught by the round-2 review).
Documentation
Section titled “Documentation”generateId()carries a SECURITY JSDoc (src/internal.ts): theMath.random()fallback used on legacy WebViews is now explicitly documented as not cryptographically strong. Callers crossing a real trust boundary should layer a signed nonce on top of the envelope payload rather than relying on ID unpredictability.
Removed (packaging)
Section titled “Removed (packaging)”- Removed Traditional-Chinese llms files (
llms_ZHTW.txt,llms-full_ZHTW.txt): aibridgejs was the only ai*js package shipping localised LLM files; aifsmjs and aiecsjs ship English llms only. LLM agents ground in English; the ~27 KB of duplicated content was net cost (extra tarball size + sync burden) for no consumer.README_ZHTW.mdand human-facing translations stay.
Added (tooling)
Section titled “Added (tooling)”verify:llmsgate (scripts/build-llms-full.mjs): the script now accepts--check, which builds the file in memory and exits non-zero if it differs from disk. Wired intoprepublishOnly. Works pre-commit and in CI alike (the previous form would have requiredgit diff --exit-code, which fails any time the working tree has uncommitted changes).
Changed (API)
Section titled “Changed (API)”Bridge.callis now generic:call<T = unknown>(method, payload?, options?): Promise<T>. Existing callers that omit the type parameter keepPromise<unknown>and are unaffected. Casts likeas { token: string }should be replaced withbridge.call<{ token: string }>(...). The runtime does NOT validate the response — the generic is a caller assertion; validate with Zod / Valibot at the boundary when the host is untrusted.
Documentation
Section titled “Documentation”- New “Error semantics (retry table)” section in
README.md,README_ZHTW.md, andllms-full.txt. Each of the five error classes is now tagged retryable / not retryable, with the recommended caller response and an idiomaticcallWithReset()helper. - All
bridge.call(...) as { ... }examples migrated to the newbridge.call<{ ... }>(...)form.
Compatibility
Section titled “Compatibility”This release is non-breaking at runtime. Source compatibility is preserved for callers that did not pin the response type. Callers using as-style casts can keep them; the new generic form is the recommended replacement.
[0.1.3] - 2026-05-28
Section titled “[0.1.3] - 2026-05-28”createIframeAdapterno longer silently drops every inbound message whenexpectedSource: undefinedis passed explicitly. The source-check guard now treatsnullandundefineduniformly as “no source check”, matching the sentinel semantics used by the"expectedSource" in optionsdistinction.
Changed
Section titled “Changed”isValidEnvelopenow rejects envelopes whosetimestampisNaN,Infinity, or-Infinity. Previously only thetypeof === "number"check ran, which let non-finite numbers through.- Refactor
bridge.on()listener registration to use a definite-assignedentryinstead of anentryRefindirection object. Behaviour is identical; the change is purely for readability.
Removed (type-level, non-breaking at runtime)
Section titled “Removed (type-level, non-breaking at runtime)”BridgeAdapter.postno longer declares a secondoptions?: { signal? }parameter. No adapter implementation ever consumed it andcreateBridgenever passed it, so the runtime contract is unchanged. External adapter authors who happened to type the parameter can remove it without code changes.BridgePlatformno longer includes the"cocos"string literal. No adapter, test, or doc referenced it. Future platforms will be added together with their adapter implementation.
Internal
Section titled “Internal”IframeAdapter.dispatchTestMessageis now annotated@internal(JSDoc). Still exported for the existing vitest suite, but signalled as not part of the public contract.
[0.1.2] - 2026-05-28
Section titled “[0.1.2] - 2026-05-28”Security
Section titled “Security”- Upgrade
vitest2.1.9 -> 4.1.7 and@vitest/coverage-v82.1.9 -> 4.1.7 to resolve two Dependabot advisories on the transitive dev-only graph:- GHSA-67mh-4wv8-2f99
esbuild <=0.24.2CORS development server data leak (fixed in 0.25.0). - GHSA-4w7w-66w2-5vf9
vite <=6.4.1path traversal in optimized deps.maphandling (fixed in 6.4.2 / 7.3.2 / 8.0.5).
- GHSA-67mh-4wv8-2f99
- Add
vite8.0.14 as a direct devDependency to satisfy vitest 4 peer range (^6 || ^7 || ^8).
Changed
Section titled “Changed”- Relax statements coverage threshold from 100% to 95%. Vitest 4 with v8
coverage scores defensive race-recovery if-guards (e.g.
if (!current) return;in timeout/abort/post handlers) as separate statements that are not deterministically reachable. Lines and functions stay at 100%; branches stays at 90%.
Runtime surface unchanged. Production bundles are byte-identical.
[0.1.1] - 2026-05-28
Section titled “[0.1.1] - 2026-05-28”Changed
Section titled “Changed”- No code changes. Patch release to validate the npm publish GitHub Actions workflow end-to-end.
[0.1.0] - 2026-05-28
Section titled “[0.1.0] - 2026-05-28”- Initial release.
- Core:
createBridge,BridgeEnvelopediscriminated union,BridgeAdapterinterface, five error classes (BridgeError,BridgeDisposedError,BridgeResetError,BridgeTimeoutError,BridgeRemoteError). - Mock adapter (
aibridgejs/mock): loopback transport withreceive()test hook for unit tests. - iframe adapter (
aibridgejs/iframe):postMessagetransport with mandatory exacttargetOriginandevent.sourcevalidation; rejects wildcard*. - Flutter adapter (
aibridgejs/flutter): InAppWebViewcallHandlertransport withwaitForReadyEventgating andreceive()push entrypoint. - Detection helper (
aibridgejs/detect):detectBridgeAdapterchooses an adapter by inspecting host globals (Flutter -> iframe -> mock). - Full TDD gate suite: ready gating, ID correlation, timeout rejection, abort rejection, malformed discard, origin rejection, dispose rejection.