You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Today's hardening round stopped wherever a fix would change public behaviour. Each entry gives the question, the options, the issue's or PR's recommendation if any, and the user-visible impact; the linked issue or PR holds the evidence. Items most likely to affect correctness lead each package. Held PRs #578, #599 and #600 are green and mergeable.
Three entries share one underlying question: may a state-changing update call be re-sent automatically? #622 (query hooks' default retries), #600 (a global mutation retry reaching execute()) and the remaining #564 item (the hook's retry on an update's call()) all follow from that rule, so deciding it first settles all three.
core
#578 (held PR) Should createPollingStrategy time out requests after 5 minutes by default?
Impact: a call polling past 5 minutes rejects instead of hanging, though the canister may still run it.
#647 Should fetchQuery() and factory .fetch() keep rejecting with TanStack's CancelledError, which is not a documented reactor error, when a sign-in or sign-out interrupts them?
Options: (1) refetch under the new identity; (2) rethrow as CallError; (3) document it. The audit recommends 1.
Impact: route loaders get the new identity's data instead of an error boundary.
#642 Should a callConfig.agent query stop sharing a cache entry with the default agent's, which serves one principal's answer to another?
Options: (1) an agent segment in overridden keys; (2) document a distinguishing queryKey; (3) throw or warn without one. The audit recommends 1.
Impact: override queries reach the replica; other keys are unchanged.
#643 On Codespaces and Gitpod, should a ClientManager without host use the page origin, not mainnet, and stop auto-trusting ic_env cookies that strangers' workspaces can set?
Options: (1) origin, cookie trusted only with allowEnvConfig: true; (2) origin, trust kept; (3) routing kept, trust dropped. The audit recommends 1.
Impact: codespace dev apps reach their own replica; canister IDs from the cookie there need allowEnvConfig: true.
#646 Should reactorRetry stop retrying HTTP 4xx refusals, such as an expired delegation that takes 16 requests and about 20 s to fail?
Options: (1) no 4xx retry except 408 and 429; (2) retry 4xx once; (3) document retryTimes: 0. The audit recommends 1.
Impact: a lapsed session errors after the agent's own 4 requests; 5xx, 408 and 429 still retry.
#565 items 2–3 How should display values tell an enabled but empty opt vec from none (a form's [] is sent as none), and a _type variant arm from the discriminator (resolving it throws)?
#633 Should DisplayReactor keep vec record { text; T } as an object, which drops repeated keys (a second Set-Cookie) and reorders numeric-looking ones?
Options: (1) keep it, document; (2) array of pairs, breaking icrc1_metadata and ICRC-3 shapes; (3) object only when lossless. The audit recommends 1 now, 2 at the next major.
Impact: docs only until then.
#632 Should DisplayReactor accept NaN, ±Infinity and -0 on encode, so a float read from a canister can be sent back?
Options: (1) accept them; (2) display them as strings, changing the type; (3) docs only. The audit recommends 1 plus docs.
Impact: such values round-trip; JSON still turns them into null, now documented.
#593 Should fromZodSchema support async refinements, and should callMethod(), callMethodWithValidation() and validate() wrap a throwing validator alike?
Options: opt-in { async: true } or document sync-only; wrap as CallError with cause or document. The audit recommends the opt-in and the wrapping.
Impact: async schemas work in validate() and callMethodWithValidation(); code matching a validator's raw error must read cause.
#595 (closed; docs fixed in #596) Should Reactor.fetchQuery stay cache-first, returning invalidated data, or become stale-aware?
Options: keep it; accept revalidateIfStale (needs a peer-floor bump from @tanstack/query-core 5.0.0, or an untyped pass-through); adopt TanStack's fetchQuery semantics. No recommendation.
react
#621 Should useAuth() report isAuthenticating: true until the first session restore settles, so the guides' ProtectedRoute stops bouncing signed-in users to /login?
Impact: no redirect on reload; signed-out visitors and SSR HTML briefly see the loading state, and a hung restore holds it.
#622 Should query hooks and factories stop retrying update methods by default, since every re-run executes the update again?
Options: (1) docs only; (2) no retry for updates unless retry is set, or SysTransient only; (3) a dev warning; (4) reuse the request id. The audit recommends 1 and 2 (SysTransient only).
Impact: a lost response becomes an error, not a second execution; focus refetches remain; explicit retry wins.
#600 (held PR, #564 item 1) Should createMutation(...).execute() run through the MutationCache, like useMutation()?
Options: (1) the PR; (2) without the factory's onMutate/onSettled; (3) evicting settled mutations; (4) keep it outside. The PR recommends 1.
#599 (held PR, #564 item 3) Should useActorMethod await its invalidateQueries refetches before onSuccess and call() resolve, like the other mutation paths?
Impact: onSuccess and await call() see fresh data but land later; isPending lasts until the slowest active refetch.
#564 (remaining item) Should useActorMethod's call() for an update method apply the hook's retry, retryDelay, networkMode and meta, which it silently ignores today?
Impact of B: server imports of Reactor build, hook imports fail with a clear error, and the exports map changes.
candid
#611 Should MetadataReactor emit Candid-typed defaultArgs for func-record callbacks, and should forms accept an empty text?
Options: Candid-typed defaults or converting on that path; accepting "" or documenting "Required". The audit recommends Candid-typed defaults and accepting "".
Impact: callMethod({ args: defaultArgs }) stops throwing, with bigint defaults; empty-text methods become callable.
#606 (closed; fixed in #618) Should a url field's inputProps.type stay "url" now that its schema accepts paths like /metrics?
Options: keep it (a test pins it), so a browser <form> still rejects paths; change it. No recommendation.
#644 How should candid reactors stop each leaving a permanent ClientManager subscription?
Options: (1) compute didjsCanisterId on read; (2) add dispose(); (3) one shared adapter per manager. The audit recommends 1.
Impact: dynamic reactors stop piling up callbacks that run on every identity change; nothing to adopt.
parser
#631 Should fields and variant tags named like _0_ print under their hash, so they encode by their name's hash, not as id 0?
Options: (1) print them hashed in didToJs and didToTs; (2) reject them; (3) leave it to upstream. The audit recommends 1, plus filing 3 upstream.
Impact: these interfaces work, but their keys change (_0_ becomes _4735054_); a hand-written .did that spells a Motoko numeric field _0_ breaks.
vite-plugin / codegen
#664 Should the vite plugin re-detect icp state after vite dev starts, so a later deploy needs no restart?
Options: (A) re-detect on page loads, cached; (B) only until every canister resolves; (C) stay static, fix the warning. The audit recommends B, with /api following detection.
Impact: deploying after starting the dev server works on the next reload; a fresh-network redeploy still needs a restart.
#565 item 1 Should the plugin reject two entries sharing name and outDir, as the CLI does?
Options: fail with the CLI's message; leave it. The audit recommends failing, calling it a small, safe change.
Impact: that config fails the build instead of producing nondeterministic output with exit 0.
docs / process
#666 item 4 Which icp-cli version should the examples target, now that vite-plugin-demo uses a sync step icp-cli 1.5 removed (current users can't deploy it) while CI pins 1.2.0?
Options: stay on 1.2.0 and say so; move examples and CI to 1.5. No recommendation.
#634 Should the @icp-sdk/core quirks (U1–U9) and candid_parser/bindgen issues be reported upstream?
Today's hardening round stopped wherever a fix would change public behaviour. Each entry gives the question, the options, the issue's or PR's recommendation if any, and the user-visible impact; the linked issue or PR holds the evidence. Items most likely to affect correctness lead each package. Held PRs #578, #599 and #600 are green and mergeable.
Three entries share one underlying question: may a state-changing update call be re-sent automatically? #622 (query hooks' default retries), #600 (a global mutation
retryreachingexecute()) and the remaining #564 item (the hook'sretryon an update'scall()) all follow from that rule, so deciding it first settles all three.core
#578 (held PR) Should
createPollingStrategytime out requests after 5 minutes by default?timeoutMs: Infinityopts out); no default. No recommendation. Merging fixes core: the README's polling example times out every call after 5 minutes of uptime, and a shared createPollingStrategy leaks state between calls #563 (calls failing after 5 minutes of uptime) either way.#647 Should
fetchQuery()and factory.fetch()keep rejecting with TanStack'sCancelledError, which is not a documented reactor error, when a sign-in or sign-out interrupts them?CallError; (3) document it. The audit recommends 1.#642 Should a
callConfig.agentquery stop sharing a cache entry with the default agent's, which serves one principal's answer to another?queryKey; (3) throw or warn without one. The audit recommends 1.#643 On Codespaces and Gitpod, should a
ClientManagerwithouthostuse the page origin, not mainnet, and stop auto-trustingic_envcookies that strangers' workspaces can set?allowEnvConfig: true; (2) origin, trust kept; (3) routing kept, trust dropped. The audit recommends 1.allowEnvConfig: true.#646 Should
reactorRetrystop retrying HTTP 4xx refusals, such as an expired delegation that takes 16 requests and about 20 s to fail?retryTimes: 0. The audit recommends 1.#565 items 2–3 How should display values tell an enabled but empty
opt vecfrom none (a form's[]is sent as none), and a_typevariant arm from the discriminator (resolving it throws)?[[]], or change core's[]-is-none rule (fix(core): accept the canonical Candid optional forms in display args #273); the fix must also cover nested shapes such asopt vec vec T. Item 3: none listed. No recommendation.#633 Should DisplayReactor keep
vec record { text; T }as an object, which drops repeated keys (a secondSet-Cookie) and reorders numeric-looking ones?icrc1_metadataand ICRC-3 shapes; (3) object only when lossless. The audit recommends 1 now, 2 at the next major.#632 Should DisplayReactor accept NaN, ±Infinity and -0 on encode, so a float read from a canister can be sent back?
null, now documented.#593 Should
fromZodSchemasupport async refinements, and shouldcallMethod(),callMethodWithValidation()andvalidate()wrap a throwing validator alike?{ async: true }or document sync-only; wrap asCallErrorwithcauseor document. The audit recommends the opt-in and the wrapping.validate()andcallMethodWithValidation(); code matching a validator's raw error must readcause.#595 (closed; docs fixed in #596) Should
Reactor.fetchQuerystay cache-first, returning invalidated data, or become stale-aware?revalidateIfStale(needs a peer-floor bump from@tanstack/query-core5.0.0, or an untyped pass-through); adopt TanStack'sfetchQuerysemantics. No recommendation.react
#621 Should
useAuth()reportisAuthenticating: trueuntil the first session restore settles, so the guides'ProtectedRoutestops bouncing signed-in users to/login?#622 Should query hooks and factories stop retrying update methods by default, since every re-run executes the update again?
retryis set, or SysTransient only; (3) a dev warning; (4) reuse the request id. The audit recommends 1 and 2 (SysTransient only).retrywins.#600 (held PR, #564 item 1) Should
createMutation(...).execute()run through theMutationCache, likeuseMutation()?onMutate/onSettled; (3) evicting settled mutations; (4) keep it outside. The PR recommends 1.useIsMutating, mutation defaults (a globalretrynow re-sends these calls; see design: an update method used through the query hooks runs again on every focus, reconnect, remount and retry, each time as a new call #622) and the factory'sonMutateapply; offline calls pause; in Node, settled mutations pile up unlessgcTimeis set.#599 (held PR, #564 item 3) Should
useActorMethodawait itsinvalidateQueriesrefetches beforeonSuccessandcall()resolve, like the other mutation paths?onSuccessandawait call()see fresh data but land later;isPendinglasts until the slowest active refetch.#564 (remaining item) Should
useActorMethod'scall()for an update method apply the hook'sretry,retryDelay,networkModeandmeta, which it silently ignores today?retryre-sends state-changing calls; all butretry; document the gap. No recommendation; decide with design: an update method used through the query hooks runs again on every focus, reconnect, remount and retry, each time as a new call #622.#679 Should
@ic-reactor/reactadd areact-serverexport condition so server components can import core classes from it?react-serverentry re-exporting core; (C)"use client"hooks, advised against. The audit recommends A now, B if App Router matters.Reactorbuild, hook imports fail with a clear error, and theexportsmap changes.candid
#611 Should
MetadataReactoremit Candid-typeddefaultArgsfor func-record callbacks, and should forms accept an emptytext?""or documenting "Required". The audit recommends Candid-typed defaults and accepting"".callMethod({ args: defaultArgs })stops throwing, with bigint defaults; empty-text methods become callable.#606 (closed; fixed in #618) Should a
urlfield'sinputProps.typestay"url"now that its schema accepts paths like/metrics?<form>still rejects paths; change it. No recommendation.#644 How should candid reactors stop each leaving a permanent
ClientManagersubscription?didjsCanisterIdon read; (2) adddispose(); (3) one shared adapter per manager. The audit recommends 1.parser
#631 Should fields and variant tags named like
_0_print under their hash, so they encode by their name's hash, not as id 0?didToJsanddidToTs; (2) reject them; (3) leave it to upstream. The audit recommends 1, plus filing 3 upstream._0_becomes_4735054_); a hand-written .did that spells a Motoko numeric field_0_breaks.vite-plugin / codegen
#664 Should the vite plugin re-detect
icpstate aftervite devstarts, so a later deploy needs no restart?/apifollowing detection.#565 item 1 Should the plugin reject two entries sharing
nameandoutDir, as the CLI does?docs / process
#666 item 4 Which icp-cli version should the examples target, now that
vite-plugin-demouses a sync step icp-cli 1.5 removed (current users can't deploy it) while CI pins 1.2.0?#634 Should the
@icp-sdk/corequirks (U1–U9) and candid_parser/bindgen issues be reported upstream?__proto__workaround into core's reply decoding. No recommendation; design(parser): a Candid field or variant tag named like_0_is sent as field id 0, not by its name's hash #631 recommends filing its part.Checklist
fetchQueryacross a sign-in/out (audit: 1)opt vec;_typearmvec record { text; T }result loses repeated keys and the order of numeric-looking keys, e.g. an HTTP response's second Set-Cookie header #633 — object keys: docs now, pairs later (audit)fetchQuerystalenessisAuthenticatingbefore the first restore (audit: 1)execute()via theMutationCache(PR: 1)onSuccesscall()@ic-reactor/reactin a React Server Component, not even the core classes it re-exports #679 —react-serverexport conditiontext(audit)urlfield'sinputProps.type_0_is sent as field id 0, not by its name's hash #631 —_N_field names (audit: 1)vite devstarts, so a canister deployed afterwards never gets its id until the server restarts #664 — dev-server re-detection (audit: B)name+outDir