Docs/guidesv1.0.0-rc.1

Evaluating the 1.0 release candidate

This guide is for 1.0.0-rc.1, not a stable 1.0 migration guarantee.

Some corrections listed below describe source changes after RC publication. The source still carries RC.1 metadata; it is not proof those changes exist in an already published archive. Check installed declarations, the exact release commit and source/release evidence.

  1. Save a known-good application commit and lockfile. Use a staging environment.
  2. Upgrade to Node >=22.17.0 and npm >=9; use ESM and compatible TypeScript settings.
  3. Install the exact RC: npm install --save-exact @tagna/udiot@1.0.0-rc.1.
  4. Replace unpublished deep imports with public entry points.
  5. Compile with strict checking, then run application/service/browser tests.
  6. Validate a staged rollout and retain a rollback version/lockfile.

Changes to review explicitly

  • Public npm installation needs no GitHub Packages scope mapping or token.
  • Root Action is a decorator; use StoreAction for action-object types.
  • Root Middleware is a legacy state type, not the internal pipeline decorator.
  • Root Component is an interface; the DI decorator is ComponentDecorator.
  • Legacy module/schema/reflection declarations may be type-only exports.
  • /ssr, /isr, /middleware, /types and similar source-oriented subpaths are not exported. Follow current web/server and validation guides.
  • JWT validation uses an explicit algorithm allowlist (HMAC, or RSA/ECDSA with a public key) and requires exp by default. API-key/session strategies require validator callbacks; mere credential presence is insufficient.
  • Shared rate-limit stores must provide atomic increment(key, windowMs).
  • Preserve request/tenant isolation and review cache behavior for private data.
  • Review generated templates; unsupported internal imports and business-logic placeholders are not fixed merely by installing the package.

Upgrading from 1.0.0-rc.1

The next candidate fixes defects found in review and tightens several defaults. Each row says what you would notice and what to change. Where a stricter default blocks a request, the server logs a one-time hint naming the option involved.

Area Change What you would notice What to do
DI Singletons registered on a parent container are shared by request and tenant scopes; a singleton that depends on a SCOPED provider is built once per scope Services that were silently rebuilt per request are now built once Mark services that hold per-request state ServiceScope.SCOPED
Controllers A handler that returns nothing and takes no @Res() answers statusCode, or 204 Requests that used to hang now complete None; use @Res() to write the response yourself
Web errors The final error handler keeps 4xx statuses and serialises HttpError Malformed JSON returns 400, not 500 Update tests that expected 500
Diagnostics Route manifest, diagnostics, config dump and probe check messages are shown only when NODE_ENV is development or test 404 on /__udiot/* and /diagnostics/config where NODE_ENV is unset or production Set NODE_ENV locally, or exposeDiagnostics: true or a per-request function
Proxies New trustProxy setting Behind a TLS proxy, sessions did not persist and IP limits lumped clients together Set trustProxy: 1 (or your hop count)
Rate limits user and userOrIp limits run after @RequireAuth Per-user limits now count per user Use afterAuth to override
CSRF Unsafe requests with a foreign Origin/Referer, or Origin: null, get 403 Cross-origin request blocked Add legitimate origins to trustedOrigins; call csrf.rotate(req) after login
Sessions 7 days of inactivity (rolling), table udiot_sessions, X-Powered-By removed Existing cms_sessions rows are ignored, so users sign in again Set tableName: 'cms_sessions' to keep them
JWT requireExp defaults to true; RS*/ES* algorithms with publicKey 401 for tokens without exp Issue tokens with exp, or set requireExp: false
Uploads Stored extension follows the validated MIME type; content checks on by default Spoofed files rejected; unknown risky extensions saved as .bin Set verifyMagicBytes: false only for trusted sources
Templates nl2br escapes its input and returns safe HTML Line breaks render without | safe Remove | safe after nl2br; it is no longer needed
Component templates Expressions are parsed, not evaluated; only context values and Math, JSON, Number, String, Boolean, Date and a few helpers are reachable; no new or assignment A binding that used another global renders empty and logs an error Pass the value or helper in the render context
SSE Events carry ids for Last-Event-ID replay; slow clients are disconnected New id: lines in the stream replayBufferSize: 0 turns ids off
Agents runWithTools keeps tool calls on assistant turns and uses retries and telemetry Multi-turn tool use works against OpenAI and Anthropic Set toolCalls on assistant messages when building tool conversations by hand
Agents No built-in vendor prices; costUSD is undefined unless you pass priceTable costUSD missing from responses and run events Pass your own priceTable if you need dollar figures
Agents A generic apiKey goes to one vendor only Anthropic calls fail if they relied on a shared OpenAI-style key Use anthropicApiKey / openaiApiKey
Agents Tool schemas close objects (additionalProperties: false) and reject types with no JSON Schema form describe() throws for z.function() and similar Use JSON-representable input schemas
Agents AgentLoop checks oscillation per iteration Loops with pass-through steps no longer stop early None
Pipeline Recovery runs once at the failing middleware; retry only before next(); a second next() call throws Fewer duplicate retries Remove double next() calls
Tenancy A signed-in user without a tenant claim needs authorizeTenant to pick a tenant by header or subdomain 403 Tenant selection requires authorization Pass authorizeTenant(user, tenantId) or put tenant_id in the token
Sandbox Children get an allow-listed environment; spawn failures reject; output capped at 1 MiB per stream; process trees are killed Commands miss host variables; truncated: true on long output Pass env, envAllowList or inheritEnv: true; raise maxOutputBytes
Remote sandbox A token over plain http:// to a remote host is refused Constructor throws Use https://, or allowInsecureHttp: true
HMR The dev server binds localhost and checks Origin Other devices or origins cannot connect Set host and allowedOrigins
Packaging Integrations are optional peer dependencies: typescript, openai, @anthropic-ai/sdk, firebase, bullmq, ioredis, @mikro-orm/*, pg, connect-pg-simple, nunjucks (server templates) and inquirer (interactive CLI prompts); chalk, ora and boxen are no longer installed Installing @tagna/udiot no longer pulls them in; using a feature without its peer fails with code UDIOT_OPTIONAL_PEER_MISSING naming the package Install the peers you use (see the README table)
Database Firebase helpers moved from @tagna/udiot/database and @tagna/udiot/database/browser to @tagna/udiot/database/firebase; @tagna/udiot/database no longer re-exports the MikroORM MySQL/PostgreSQL drivers or Migrator Import errors for those names Import Firebase helpers from the new entry point and driver APIs from @mikro-orm/postgresql, @mikro-orm/mysql or @mikro-orm/migrations
DI Factories default to SINGLETON like classes; request and tenant containers are disposed when the response ends (onDestroy(), dispose(), Symbol.dispose) A factory that ran per resolve() now runs once; per-request services are cleaned up Register per-call factories with scope: ServiceScope.TRANSIENT
Web server Request ids (X-Request-Id, req.requestId), a bodyLimit (default '100kb') and graceful stop({ timeoutMs }) New response header; bodies over the limit get 413 Raise bodyLimit for larger payloads
State store The reducer runs at the end of the middleware pipeline; dispatch() rejects when a middleware or the reducer throws, or when a non-action reaches the reducer Middleware errors no longer let the action through; code after await next() sees the new state Catch dispatch errors where you relied on them being swallowed; add thunkMiddleware() to dispatch functions
State middleware A legacy (store, action) middleware that returns nothing consumes the action, as documented; loggerMiddleware() and performanceLogger() are pipeline middleware (collapsed/colors removed; performanceLogger().getStats() replaces random log output) Actions vanish after a middleware that forgot return action Return the action; drop collapsed/colors
Thunks thunkMiddleware() and legacyAdapters.thunk() await the thunk; createAsyncThunk failures are reported once, as /rejected await store.dispatch(thunk) waits for the thunk None
Selectors createSelector(fn) recomputes when the state changes (it returned its first result forever); @Selector() methods too Derived values update None
Store asObservable() emits each change once (it emitted twice); undo/redo restore frozen state and report the previous state; persisted partial state is merged into the current state Fewer duplicate emissions None
Persistence flush() writes the pending state (it discarded it), overlapping saves queue and keep the newest, remove() drops pending saves Saves that were silently lost are written None
Store decorators @Persist, @EnableDevTools and @AIPowered set up in the constructor and observe actions after the reducer; @Action debounce and throttle are per instance and every debounced caller settles; batchMutations() is async and applies one @@BATCH change DevTools and AI see the post-reducer state await batchMutations(...)
Component decorators Setting a @State property invalidates @Computed values; invalidateComputed() works; subclass metadata no longer leaks into the parent; @Component registers props by name; @AIComponent registers with AIComponentRegistry and no longer logs unimplemented features as enabled Computed values update None
Component templates The parser handles sibling elements, text mixed with elements, void and self-closing tags; several top-level nodes are wrapped in a div Templates with siblings render correctly; inner text keeps its spacing Check templates that relied on the old single-element parse
Route validation Array item errors are reported as body.tags[1] (was body.tags[1].item); UUID versions 1 to 8 are accepted Field paths in 422 responses change Update clients that match on field paths
HTTP caching shouldReturn304 lets If-None-Match decide alone (weak comparison) and compares dates to the second Fewer wrong 304s and more correct ones None
Pipeline retry The retry recovery strategy only retries middleware marked idempotent: true A failing middleware that was retried now fails at once Set idempotent: true on middleware that is safe to run twice, such as reads
HMR bundler plugins The webpack and esbuild HMR plugins (never exported) are removed with their optional peers; the Vite plugin's trackDependencies option is removed and it no longer makes modules self-accept Vite propagates updates to importers instead of leaving stale bindings Drop trackDependencies from udiotHMRPlugin() options
Dev tools AIPerformanceOptimizer.autoOptimize() and the codeChanges of its recommendations are removed; @PreserveState ids default to the class name and take an optional hot handle Saved component state is restored after a reload Treat recommendations as advice; pass componentId if two classes share a name
CLI generators Generated code imports from @tagna/udiot and compiles with "module": "NodeNext"; generate and create ask before writing (--yes skips the question, a non-interactive shell needs it); --with-stories is removed Scripts that ran udiot generate stop with a request for --yes Add --yes to scripted generation
CLI wizards and create Wizards write the files they preview (they wrote nothing before); create calls the configured model through the openai peer (it returned canned output) and supports components, services, controllers, events and handlers Real files and real provider calls Install openai and set OPENAI_API_KEY for create; use wizard ... --force to overwrite
Component props @Prop() no longer infers Object from design metadata (TypeScript emits it for any, unknown, unions and interfaces); PropsValidator accepts primitives for String/Number/Boolean props and accepts a class; ComponentFactory.create() throws on invalid props instead of logging @Prop() value!: string | number accepts strings; invalid factory props fail fast Pass type explicitly where you relied on the inferred Object check
Components BaseComponent.unmount() removes what mountTo() rendered; ComponentFactory.generateFromIntent() and generateFromPattern() (which always threw) are removed; fromTemplate() reads selectors with several hyphens and single-quoted attributes; once-listeners that throw run once Unmounted components leave the page Use udiot create for AI generation
AI helpers AIComponentGenerator, GenerationStats, ComponentTestGenerator and testGenerator are removed (no model calls, placeholder output, tests that did not parse); AutoOptimizer now runs the analysis on its timer; AIPredictor and StateAnalyzer report the anomalies and cycles they used to miss Import errors for the removed names; AutoOptimizer subscribers receive suggestions Use udiot create and udiot generate --with-tests
UI components Button children, Card titles and Input labels, values, placeholders and errors are HTML-escaped; mounted buttons call onClick and inputs call onChange; Modal closes with its button or Escape; DragDropManager.destroy() removes its listeners Markup in a button label shows as text Put markup in Card content, which stays HTML
Enterprise helpers HttpClient refuses endpoints on another origin than its base URL; Router evaluates route guards and matches on path segments; Link renders a plain anchor followed by the router (no inline onclick); required form fields accept 0 and false; GlobalErrorHandler passes rejection reasons through unchanged /user no longer matches /users; cross-origin endpoint strings throw Use a second client for another origin
Services ConfigService refuses __proto__, prototype and constructor key segments; ValidationService min, max and oneOf check 0; RouterService ignores query strings and decodes params; StateService.delete() notifies subscribers and keeps them; AnalyticsService no longer logs event properties; RedisAdapter loads ioredis as an optional peer min(1) rejects 0 None
File-based routing AutoRouter.handler() serves the discovered routes (they were registered but never served, and API routes lost their HTTP method); route files load by file URL; hot reload imports fresh modules instead of using require.cache; files starting with _ are never routes; only the first directory decides an API route (pages/capital.ts is a page) Routes answer requests Mount router.handler(); rename _-prefixed files that should be routes
Background jobs 'immediate' schedules run once (they re-enqueued themselves forever); an interval with a future startAt first runs at startAt; retry.jitter is applied; dead-letter records keep the first failure time across retries Fewer duplicate runs None
Middleware hot reload New files are loaded and deleted files removed (every watch event was treated as a change); modules reload through ESM imports instead of require.cache; a middleware class is instantiated once; plain middleware functions are accepted Hot reload works in ESM projects None
SSR renderer documentShell stylesheets, links, meta and scripts are added to every page (they were dropped whenever a page had its own head config, as every createWebServer page with SEO does); inlineStyle is rendered; clearCache() imports a fresh module in ESM builds (it threw); a class component without render() fails with a clear error; the unused RenderDocumentOverrides type is removed; OpenAPI output declares controller-path parameters, the default bearer scheme and optional auth Shell assets appear on pages that lacked them Remove shell assets you added to page heads by hand
Validators Validators.string.url() accepts only http: and https: URLs unless given a protocol list (javascript: URLs passed); pattern() resets global regexes between values; number.multipleOf() tolerates floating point error; object.hasProperty() and hasProperties() report non-objects instead of throwing Other URL schemes are rejected Pass the schemes you accept, e.g. url(['https:', 'mailto:'])
Cache analyzer AICacheAnalyzer frequency is accesses per minute since a key was first seen (it was the lifetime count); trackUpdate() measures time between updates in seconds (it measured time since the last read, in milliseconds, against TTLs in seconds) and works for keys not read yet; the new trackSet(key, ttlSeconds) feeds the report's oversizedTTLs and undersizedTTLs, which were always empty; AccessPattern gains firstAccess and lastUpdate Different strategy and TTL recommendations Call trackSet() where entries are stored
SSR context SSRContext keeps = inside cookie and query values (base64 session cookies were cut short), decodes + in queries, keeps an empty first value of a repeated key, splits the URL at the first ? only and no longer throws on malformed percent-escapes; setCookie(..., { maxAge: 0 }) emits Max-Age=0; cookie names, paths and domains with separators throw; directly set Set-Cookie headers are kept Correct values where they were truncated None
Test client createUdiotTestClient keeps cookies the app sets and sends them back (as its docs described; cookies: false opts out), no longer follows redirects, and treats only http:// and https:// paths as absolute URLs Tests see 3xx responses and carry sessions between requests Follow Location yourself where a test relied on redirects
CLI misc udiot --version prints the package version; sdk publish --version is now --package-version; enhance cannot apply advice-only suggestions and its "safe" auto-fix is whitespace only; telemetry setup keeps existing alert rules --version after sdk publish printed the CLI version Use --package-version

This checklist does not replace application-specific compatibility testing or the changelog. Read support status, testing and deployment.

From the canonical UDIOT public documentation.Try it in the playground ↗