Skip to content

v0.9.0

Pre-release
Pre-release

Choose a tag to compare

@pathosDev pathosDev released this 14 May 21:57
· 2764 commits to develop since this release
8e2627b

The "public-launch readiness" release. The framework gets its own website (actor-ts.dev) with 199+ pages and full German translation; the cluster bootstrap shrinks from 15–30 lines to a single Cluster.bootstrap({ name }); eight latent security weaknesses get patched; and a code-quality sprint closes 17 audit-catalog issues.

🚀 New features

Persistence

  • eventDispatcher<S, E>() — typed builder for PersistentActor.onEvent that the compiler refuses to complete until every variant of the event union has a handler. Missing variants surface as EventDispatcherIncomplete<missing> type errors at the build site (#239).

Chat sample feature sweep

  • User-created rooms at runtimeChatRoomDirectoryActor wraps a cluster-wide DistributedData ORSet; protocol gains create-room / room-added / room-removed; six frontends grow a "+ new room" input (#98).
  • Private direct messages — DMs ride existing protocol frames as virtual @<username> rooms; sharded DmChannelActor keyed on the canonical pair-id; each user subscribes once to their inbox topic (#100).
  • Typing indicators — ephemeral TypingBroadcast via the room's PubSub topic; clients debounce at 1/2 s and auto-clear after 3 s (#103 slice 1).
  • Read receipts — per-room read-up-to.<room> DistributedData LWWMap; ReadReceiptsActor enforces a monotonic guard at the boundary; frontends render ✓ / ✓✓ on own messages (#103 slice 2).
  • Production-realistic auth — scrypt-hashed passwords (N=16384/r=8/p=1, constant-time verify); HMAC-SHA256-signed JWT-style session tokens self-validate without a DD read; revocation set in DD-LWWMap (#99).

⚠️ Security

Eight latent security weaknesses patched. All defenses are at the deserialisation / boundary layer with regression tests pinning both the attack vector and the legitimate path.

  • Wire-frame size capcluster/protocol rejects frames claiming gigabyte+ lengths before allocation; defeats a 4-GiB-claim memory-exhaustion DoS. Configurable; Infinity cap remains the escape hatch.
  • Path-traversal block in FilesystemObjectStorageBackend — keys containing .. or absolute-path patterns rejected at the boundary instead of being resolved through to disk.
  • Memcached protocol injectionMemcachedCache keys validated against the 250-byte / printable-ASCII rule before being placed on the wire; defeats injection via attacker-controlled keys.
  • Gossip-version cap against permanent-down exploit — versions more than 24 h above the local wall-clock are rejected on the spot; previously a malicious peer could send version: MAX_SAFE_INTEGER to pin a healed node as down forever.
  • Snapshot-seq validation on recoveryPersistentActor rejects snapshots whose seqNr is non-monotonic with the journal; defeats tampered-snapshot replay.
  • WebSocket inbound frame size capWebSocketActor rejects oversized inbound frames before assembly; defeats memory-exhaustion DoS via fragmented frames.
  • Duplicate-identity hello rejectioncluster/transport refuses a second hello frame claiming an already-connected identity; defeats peer-hijack where an attacker rebinds to a victim's from address. Legitimate reconnect (after clean close) unaffected.
  • Idempotency-key cache bindinghttp/cache/idempotency ties each cached response to the request fingerprint (method + path + body hash) so a poisoned key can't replay one response across different requests.

✨ Quality of life

API shortcuts

  • Cluster.bootstrap({ name }) — one-call setup that builds the ActorSystem, joins the cluster, starts the Receptionist, and wires SIGTERM / SIGINT shutdown. Discovery defaults to an env-driven chain (CLUSTER_SEEDS → Kubernetes API → DNS) so the same code runs single-node in dev and joins an existing cluster in production without a config change.
  • cluster.sharding.start('cart', CartActor, { extractEntityId }) — getter on Cluster plus class-shorthand on ClusterSharding.start(); replaces the previous ClusterSharding.get(system, cluster) + Props.create(() => new CartActor()) ritual.
  • ref.ask<TRes>(msg, timeoutMs?) — method form of the ask pattern with auto-injected replyTo. The free ask(ref, msg) function is removed (pre-1.0, no compat shim).
  • system.spawnTyped(behavior, name) + system.spawnTypedAnonymous(behavior) — method form symmetric to spawn / spawnAnonymous; same pair lands on ActorContext for typed-child creation from untyped parents. The free spawnTyped() + spawnTypedChild() functions are removed.
  • await system.http(8080).bind(routes) — Fastify-default HTTP shortcut. system.extension(HttpExtensionId).newServerAt(...) still works for non-default backends.
  • ActorSystem.create('app', { persistence: { journal, snapshotStore } }) — wire real persistence backends at creation time instead of poking the extension after the fact.

Code hygiene

  • Pattern-match exhaustiveness pass — 9 discriminator-union dispatch sites converted from if/else-or-switch to match(...).exhaustive(); adding a new union variant without a matching arm now fails the typecheck. Touches BrokerActor.enqueueOutbound, JetStreamActor / MqttActor / KafkaActor cmd dispatch, BackoffSupervisor, HoconParser, Compression, BodyCodec, PersistentActor (#230, #232, #233, #234, #239, #240, #241, #243, #244).
  • DRY helperssrc/util/Constants.ts centralises duplicated defaults (gossip interval, ask timeout, tombstone TTL, seed-retry); src/util/LazyImport.ts is the uniform peer-dep import + "missing package" error; src/util/WrapError.ts is the typed-error wrap helper with double-wrap prevention (#257, #252, #254).
  • Typed namessrc/config/ConfigKeys.ts is the typed const-tree for every HOCON path; src/persistence/storage/KeyValidator.ts is a declarative rule-based factory replacing hand-rolled key-safety checks (#265, #251).
  • Naming consistency — every message union now uses kind as discriminator (not a mix of type / op / cmd); ActorSystem.actorOf is gone in favour of spawn / spawnAnonymous; the redundant actor-ts. prefix on worker message kinds is dropped.

📚 Documentation

  • Public website at actor-ts.dev — Astro Starlight site under docs/, 199+ pages across the 12-Part IA, full Quickstart + fundamentals + per-subsystem deep-dives + migration guides + API reference (TypeDoc).
  • Full German translation — every page mirrored under /de/. Seven additional UI locales (fr, es, ja, ko, pt-BR, ru, zh-CN) staged with sidebar labels translated; full content translations tracked as open issues (#300#306).
  • Mermaid diagrams throughout — replaces ASCII art across all subsystem pages (cluster, sharding, distributed-data, persistence, observability, operations, testing, IO, delivery).
  • Landing-page polish — animated particle-network hero, prose-driven "What is actor-ts" cards, See-it-in-action status grid, custom-domain redirect, mobile-responsive splash.
  • Issue templates + security disclosure flow.github/ISSUE_TEMPLATE/ gains security_report.yml; bug template gets a security-flag checkbox.