Foundation Util

  • Area: Foundation
  • Path: foundation/util
  • Kind: Shared primitives crate

Role in the stack

koder-foundation-util factors out primitives that were copied across ai/recsys, foundation/ads, and foundation/moderation during their independent evolution. One source of truth means bug fixes and performance improvements land once.

Primitives

  • RateLimiter — token-bucket per tenant. allow(tenant) -> bool +

    prune_idle(secs) + tenant_count().

  • EventSink<E> — generic trait over the event type E. Default

    impls: NoopSink (discards), InMemorySink<E> (bounded ring-buffer for tests/ops).

  • Gateis_blocked(scope, item) -> bool for the moderation /

    brand-safety gate pattern. Default impls: NoopGate, StaticGate (in-process set; production wires HTTP adapter to foundation/moderation).

Consumers

Crate Uses
ai/recsys RateLimiter, EventSink<RecsysEvent>, Gate
foundation/ads RateLimiter, EventSink<AdsEvent>, Gate
foundation/moderation RateLimiter, EventSink<ModerationEvent>

Each consumer keeps its domain-specific event enum and exposes type aliases (e.g., RecsysEventSink = dyn EventSink<RecsysEvent>) so call-site readability stays unchanged.

Why a crate, not a module

A shared module across crates would require either workspace restructuring or git-subtree gymnastics. A real cargo dependency keeps the boundary explicit and lets each consumer pin a version independently when one needs to evolve faster than the others.

Test coverage

16 unit tests covering rate-limit refill semantics, sink ring-buffer overflow, gate scope isolation, and Arc-dyn shape verification.