Releases: pathosDev/actor-ts
Releases · pathosDev/actor-ts
v0.9.1
Docs-only patch — the first round of post-v0.9.0 publish feedback. No code changes; bumping for the README rendering fix on the npm package page.
🐛 Fixed
- README logo no longer 404s on npmjs.com — relative
./docs/public/logo.pngswitched to an absoluteraw.githubusercontent.com/pathosDev/actor-ts/main/...URL. Relative paths inside raw<img>tags aren't rewritten by npm's README renderer; only Markdown image syntax is. - License badge link — relative
./LICENSEswitched to an absolutegithub.com/.../LICENSEURL. - License section text — said "MIT" left over from the original metadata-only declaration; corrected to "Apache 2.0" matching the v0.9.0 relicense.
- Sub-package READMEs (
benchmarks/,examples/chat/,examples/voice/) referenced a non-existentassets/logo.svgpath. Switched to the same absoluteraw.githubusercontent.com/.../docs/public/logo.svgURL — consistent across every README and robust under any rendering target.
v0.9.0
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 forPersistentActor.onEventthat the compiler refuses to complete until every variant of the event union has a handler. Missing variants surface asEventDispatcherIncomplete<missing>type errors at the build site (#239).
Chat sample feature sweep
- User-created rooms at runtime —
ChatRoomDirectoryActorwraps a cluster-wideDistributedDataORSet; protocol gainscreate-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; shardedDmChannelActorkeyed on the canonical pair-id; each user subscribes once to their inbox topic (#100). - Typing indicators — ephemeral
TypingBroadcastvia 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>DistributedDataLWWMap;ReadReceiptsActorenforces 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 cap —
cluster/protocolrejects frames claiming gigabyte+ lengths before allocation; defeats a 4-GiB-claim memory-exhaustion DoS. Configurable;Infinitycap 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 injection —
MemcachedCachekeys 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_INTEGERto pin a healed node asdownforever. - Snapshot-seq validation on recovery —
PersistentActorrejects snapshots whoseseqNris non-monotonic with the journal; defeats tampered-snapshot replay. - WebSocket inbound frame size cap —
WebSocketActorrejects oversized inbound frames before assembly; defeats memory-exhaustion DoS via fragmented frames. - Duplicate-identity hello rejection —
cluster/transportrefuses a second hello frame claiming an already-connected identity; defeats peer-hijack where an attacker rebinds to a victim'sfromaddress. Legitimate reconnect (after clean close) unaffected. - Idempotency-key cache binding —
http/cache/idempotencyties 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 theActorSystem, joins the cluster, starts the Receptionist, and wiresSIGTERM/SIGINTshutdown. 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 onClusterplus class-shorthand onClusterSharding.start(); replaces the previousClusterSharding.get(system, cluster)+Props.create(() => new CartActor())ritual.ref.ask<TRes>(msg, timeoutMs?)— method form of the ask pattern with auto-injectedreplyTo. The freeask(ref, msg)function is removed (pre-1.0, no compat shim).system.spawnTyped(behavior, name)+system.spawnTypedAnonymous(behavior)— method form symmetric tospawn/spawnAnonymous; same pair lands onActorContextfor typed-child creation from untyped parents. The freespawnTyped()+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. TouchesBrokerActor.enqueueOutbound,JetStreamActor/MqttActor/KafkaActorcmd dispatch,BackoffSupervisor,HoconParser,Compression,BodyCodec,PersistentActor(#230, #232, #233, #234, #239, #240, #241, #243, #244). - DRY helpers —
src/util/Constants.tscentralises duplicated defaults (gossip interval, ask timeout, tombstone TTL, seed-retry);src/util/LazyImport.tsis the uniform peer-dep import + "missing package" error;src/util/WrapError.tsis the typed-error wrap helper with double-wrap prevention (#257, #252, #254). - Typed names —
src/config/ConfigKeys.tsis the typed const-tree for every HOCON path;src/persistence/storage/KeyValidator.tsis a declarative rule-based factory replacing hand-rolled key-safety checks (#265, #251). - Naming consistency — every message union now uses
kindas discriminator (not a mix oftype/op/cmd);ActorSystem.actorOfis gone in favour ofspawn/spawnAnonymous; the redundantactor-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/gainssecurity_report.yml; bug template gets a security-flag checkbox.
v0.8.0
🚀 New features
- DistributedData quorum writes + reads —
updateAsync(key, factory, fn, { consistency })+getAsync(key, { consistency }); levels'local'/'majority'/'all'/{ from: K }. Reads merge incoming responses before resolving; timeouts reject writes (local apply stands) (#81). - Outside-in cluster connectivity (
ClusterClient) — lightweight handle for REST frontends / batch jobs / operator scripts:send(path, msg)+ask(path, msg, ms?)with round-robin failover across contact-points (#86). reEncryptObjectStorage(backend, opts)— re-encrypt every body under a prefix to the active master key; idempotent on already-current versions;If-MatchCAS internally. Closes v0.7.0's rolling-migration Phase-3 (#70).migrateBetweenJournals/migrateBetweenSnapshotStores— copy-with-transform for backend swaps and schema piggybacks; per-pid resume + optional progress store (#87).- Extended cluster-management HTTP endpoints —
GET /cluster/shards?type=<typeName>,POST /cluster/down { address },GET /metrics(Prometheus); all opt-in (#56). Cluster.down(addr)— public API for operator force-down of a remote peer; backsPOST /cluster/down(#56).
v0.7.0
🚀 New features
- MQTT 5.0 user properties + reason codes — opt in via
protocolVersion: 5; inbound/outbound carry optionaluserPropertiesandreasonCode(silently dropped on v3.1.1) (#13). - JetStream pull-consumer mode — opt in via
consumer.mode: 'pull'; app drives batches via{ kind: 'fetch'; batch; expiresMs? }cmds (#62). - Cache bulk operations —
Cache.mget+Cache.msetacross all three backends; Redis pipelinesSET ... PXfor TTL'd msets (#14). ReplicatedEventSourcedActor.lease()— protected hook; when it returns aLease, the actor enforces single-writer perpersistenceId(non-holders observe + throw onpersist).onLeaseLost(reason)companion hook (#89).
📚 Documentation
docs/operations/rolling-migration.md— four-phase rolling-deploy walkthrough with master-key rotation interleaved (#91).docs/persistence/migration-recipes.md— decision-tree guide across five overlapping migration tools with worked examples + pitfalls section (#93).ClusterEvents.MemberRemoved— JSDoc + README clarify definitive (tombstoned) vs. FD-driven removal paths (#79).
v0.6.0
🚀 New features
- Two sample apps with six frontends each —
examples/chat/(clustered chat: sharded persistent rooms, DD-backed online users, singleton HTTP front door) andexamples/voice/(PTT / group / Teams-style rooms over WebSocket binary frames). Plain / Lit / Svelte / React / Next.js / Angular clients (#94, #95, #96, #97). - CRDTs + replicated event sourcing — full CRDT family (
GCounter,PNCounter,GSet,ORSet,LWWRegister,LWWMap,ORMap,MVRegister,GCounterMap);DistributedDatawith gossip replication;ReplicatedEventSourcedActorwith vector-clock snapshots and pluggable resolvers (#37, #45, #41). - Durable
DistributedData— CRDT state survives full cluster restart via per-replica state-store records (#40). - Persistence query + projections —
PersistenceQuery(eventsByPersistenceId/eventsByTag),ProjectionActorwith at-least-once delivery + offset persistence; push viaJournalEventBus; SQLite tag join table; multi-tagall/any/notfilter (#36, #42, #43, #44, #90). - Cluster sharding hardening — rebalance + daemon failover hardening; persistent
ShardCoordinatorallocation state; persistent Remember-Entities;maxEntities+ LRU passivation; Cassandra-backedRememberEntitiesStore; member-tombstone pruning (#35, #39, #49, #82, #84, #75). - Split-brain-safe handovers via
Lease— realKubernetesLease(replaces v0.2.0 stub); optionalLeaseonClusterSingleton+ShardCoordinator;DowningProviderwired into FD;LeaseMajorityresolver (#33, #38, #60, #61, #51). MultiNodeSpec+ParallelMultiNodeSpec— in-process and worker-thread cluster test harnesses with partition / heal helpers andawaitMembers/awaitLeader(#34, #46).- Observability stack — Prometheus export + OTel-style tracing (W3C
traceparent) +LogContextMDC; bridges toprom-clientand@opentelemetry/apikeep both SDKs optional (#11, #10, #53, #64, #63). PersistentFSM— FSM + event sourcing; guard checks, replay-driven rebuild, per-statestateTimeout, multi-event transitions viapersistAll(#52, #65, #66).BackoffSupervisor— exponential backoff with optional stash;triggerOn: 'failure' | 'stop' | 'any'; opt-in strict post-respawn message gating (#48, #68, #67).ClusterRouter— cluster-aware router with role filter and round-robin / random / consistent-hashing / broadcast strategies (#50).context.throttle({ qps, burst, onExcess })— per-actor token-bucket rate limiter (#83).- Schema migration toolkit — chain upcasters + downcasters;
writeVersionfor rolling deploys; bulk migrators; pluggable codec +InMemorySchemaRegistrywith compatibility checks (#6, #7, #9). - Master-key rotation for AES-256-GCM snapshots —
MasterKeyRingwith key-version byte in body manifest; legacy single-key bodies still readable (#8). - Production broker integrations — Kafka exactly-once via
commitMode: 'manual'; NATS JetStream actor; server-side WebSocket with Bun-native handler bindings (#2, #3, #1).
🐛 Bug fixes
DistributedPubSubMediatorgossip size + race window — frame size proportional to topic count; eager broadcast closes the ~3 % publish-after-subscribe gap (#80).FilesystemObjectStorageBackendmulti-process safety — disk-canonical FNV-1a etag; per-key lock files; atomic temp-rename writes; NTFS-quirk retries (#19).- Batched correctness items — eager peer-dep validation at plugin-init;
ORSet/GSetidentity for non-JSON values; single-actor-per-pid inReplicatedEventSourcedActor(#18, #59, #57, #58).
v0.5.0
🚀 New features
BrokerActorbase — reconnect-with-backoff (optionalCircuitBreaker), outbound buffer, subscriber fan-out, EventStream lifecycle events.- Broker actors —
TcpSocketActor,UdpSocketActor,MqttActor,WebSocketActor,KafkaActor,AmqpActor,GrpcClientActor,GrpcServerActor,NatsActor,RedisStreamsActor,SseActor. - Examples —
mqtt-temperature.ts,websocket-feed.ts,grpc-sensor.tsunderexamples/io/.
v0.4.0
🚀 New features
- Object-storage persistence —
ObjectStorageBackend+ Filesystem (built-in) + S3 (lazy AWS SDK; works with AWS, MinIO, R2, Backblaze B2, Wasabi). BodyCodec— manifest header with gzip / zstd compression and AES-256-GCM encryption (HKDF per-pid subkeys, compress-then-encrypt).- Snapshot/state stores on object storage —
ObjectStorageSnapshotStore+ObjectStorageDurableStateStorewith per-prefix codec resolvers. - Schema migration —
EventAdapter/SnapshotAdapter/StateAdapterinterfaces + versioned envelope wire format +MigrationChainupcasters +defaultsAdapterfor code-free additive evolution. - Cache abstraction —
Cacheinterface with InMemory / Redis / Memcached backends;CacheExtensionfor named registration. - HTTP middleware —
rateLimit,idempotent(Stripe-style),cached(stampede-protected response cache).
✨ Quality of life
CachedSnapshotStoredecorator — absorbs cold-start storms after sharding rebalance.
v0.3.0
🚀 New features
- Persistence stack —
Journal/SnapshotStore/DurableStateStoreinterfaces;PersistentActor(event sourcing withsnapshotPolicy) andDurableStateActor(snapshot-only with strict CAS). - Persistence backends — InMemory (default), SQLite (Bun via
bun:sqlite, Node viabetter-sqlite3, abstracted by aSqliteDriver), Cassandra (lazycassandra-driver). - HTTP service stack — directive-style DSL compiling to a backend-agnostic
CompiledRoute; Fastify (default) / Express / Hono backends, each auto-detecting the right serve primitive per runtime. HttpClient— outbound HTTP via the same backend abstraction.
v0.2.0
🚀 New features
- Configuration — HOCON parser with ENV interpolation,
Duration/Sizetypes. - Serialization — JSON + CBOR via
Serializer<T>(manifest tagging) +SerializationExtension. - Coordinated shutdown — 12-phase dependency-ordered runner;
Leaseabstraction with in-memory + Kubernetes impls. - Cluster fabric — TCP / in-memory / worker-thread transports, gossip membership, Phi-Accrual failure detection.
- Cluster sharding —
ShardCoordinator,ShardRegion, hash + least-shard allocation,Passivate,ShardedDaemonProcess. - Pub-sub + service registry —
DistributedPubSubMediator,Receptionist,ClusterSingleton,ReliableDelivery. - Split-brain resolvers —
KeepMajority,KeepOldest,StaticQuorum,KeepReferee. - Seed providers — Config, DNS (with TTL cache), Kubernetes API, Aggregate.
- Management HTTP endpoints —
/health,/ready,/cluster/state.
v0.1.0
🚀 New features
- Actor core —
Actorbase with lifecycle hooks +ActorRef/ActorContext/ActorPath/ActorSelection. - System primitives —
ActorSystem,Props,Extensionregistry, internalSystemMessagescontrol protocol. - Supervision —
OneForOneStrategy/AllForOneStrategywith Resume / Restart / Stop / Escalate directives. - Mailbox variants — unbounded, bounded (three overflow policies), priority, per-actor stash.
- Lifecycle plumbing —
ActorCell,Guardian,DeadLetterRef; death watch,ReceiveTimeout, become / unbecome, per-actorTimerScheduler. - Runtime — real-timer + manual schedulers, dispatcher variants, leveled
Logger, system-wideEventStream. - Typed Behaviors DSL — functional facade over the OO API (
receive,same,stopped,setup, supervise). - TestKit —
TestProbe+ManualScheduler(virtual clock). - Patterns —
ask,retry,CircuitBreaker,Router,after,pipeTo. FSMDSL — named-state finite-state-machine actor base.- Utility primitives —
Option<T>,Lazy<T>,Try<T>,Either<L,R>.