Skip to content

@lastshotlabs/slingshot-core

npm install @lastshotlabs/slingshot-core

Apply a public entity exposure to an underlying adapter. For readonly mode the adapter is wrapped to expose only the declared methods (with this rebound on function values). as and unsafeFullAdapter modes are type-only — the original adapter is returned unchanged. Throws when a declared method is missing on the underlying adapter so contract authors learn about drift fast.

function applyPublicEntityExposure<TValue>(adapter: TValue, exposure: PublicEntityExposureMetadata | undefined, context: { readonly entity: string; readonly contract?: string; readonly source?: string },): TValue

Source: packages/slingshot-core/src/packageAuthoring.ts

Assert that a mount path is a non-root path beginning with a slash.

Centralizes the validation rule shared by every package that accepts an HTTP mountPath option (slingshot-admin, slingshot-assets, slingshot-notifications, slingshot-organizations, slingshot-push, slingshot-search, slingshot-webhooks, etc.) so the error message follows the workspace [slingshot-<pkg>] <message> convention uniformly.

function assertMountPath(pluginName: string, mountPath: string): void

Source: packages/slingshot-core/src/configValidation.ts

Attach a SlingshotContext to a Hono app instance.

Called once by createApp() after the context is fully assembled. The context is stored as a non-enumerable property keyed by a well-known Symbol so that it does not appear in object spreads or JSON.stringify output. When the target object exposes app.use(...) (for example a Hono app in standalone tests), attachContext() also installs a lightweight request middleware that seeds c.set('slingshotCtx', ctx) so request-time helpers like getSlingshotCtx(c) work without the full createApp() bootstrap.

Remarks: Do not call from plugin or application code. This function is called exactly once per app instance by createApp() after the context is fully assembled.

Remarks: Calling attachContext more than once on the same app object with different context instances causes two categories of breakage, so this function now throws instead of allowing a second attachment:

Remarks: 1. Duplicate context per app — a second call would otherwise overwrite the first context. Any code that captured a reference to the first context via getContext(app) would then hold stale state while request middleware could still reference the old closure.

Remarks: 2. WeakMap collision — framework internals that key off the app object (e.g. the Reflect-symbol DI table) are keyed by app identity. If two contexts share the same app reference they collide on those lookups, producing hard-to-diagnose bugs where one plugin’s resolver or repo leaks into another app instance’s context.

Remarks: Plugin code should always call getContext(app) to read the context and must never attempt to create or attach one.

function attachContext(app: object, ctx: SlingshotContext): void

Source: packages/slingshot-core/src/context/contextStore.ts

Associate a PostgresPoolRuntime with a pool instance via a weak map for later lookup.

function attachPostgresPoolRuntime(pool: object, runtime: PostgresPoolRuntime): void

Source: packages/slingshot-core/src/postgresRuntime.ts

Stable plugin-state key published by slingshot-auth.

Packages that need only a narrow auth-facing peer contract should depend on this key and the accessors below instead of spelunking for raw string keys.

Source: packages/slingshot-core/src/authPeer.ts

Check whether a subscription principal is authorized to receive a given event envelope.

Uses the definition’s custom authorizeSubscriber when provided, otherwise falls back to the default scope-matching authorizer from createDefaultSubscriberAuthorizer.

function authorizeEventSubscriber<K extends EventKey>(definition: EventDefinition<K>, principal: EventSubscriptionPrincipal, envelope: EventEnvelope<K>,): boolean

Source: packages/slingshot-core/src/eventPublisher.ts

Swallow errors from a promise that must never block the main flow.

Use for fire-and-forget side effects (metadata updates, notifications, cleanup) where failure is acceptable but should be visible in logs.

function bestEffort(promise: Promise<unknown>, label?: string, logger?: Logger): void

Source: packages/slingshot-core/src/bestEffort.ts

Build a HookServices instance for an out-of-request callback.

Call this at the hook call site (typically once per hook invocation, inside the plugin’s bootstrap or runtime layer where the necessary inputs are already in scope). The returned object is safe to spread into the hook’s payload object.

function buildHookServices(args: { /** * The Hono application instance. Typed as `object` to avoid pinning a Hono * version in `slingshot-core`. Used to resolve `getContext(app).capabilityProviders` * for capability lookups and `requireEntityAdapter(app, ...)` for entity lookups. */ app: object; /** Live plugin-state map for the app instance. */ pluginState: PluginStateMap; /** Instance-scoped event bus to expose on `services.bus`. */ bus: SlingshotEventBus; /** Plugin-scoped logger to expose on `services.logger`. */ logger: Logger; /** * Default plugin name used as the `plugin:` qualifier when a hook author calls * `services.entities.get(entityModule)` without specifying a plugin. Should be * the firing plugin's own name (e.g. `'slingshot-auth'`) so hooks can read their * own entities by module reference without redundant `{ plugin: '...' }` qualifiers. */ pluginName: string; /** * Explicit manager override for manually assembled hook environments. * Framework-created apps resolve the manager from their attached StoreInfra. */ transactions?: TransactionManager; }): HookServices

Source: packages/slingshot-core/src/hookServices.ts

Build the capabilityProviders map key for a capability handle.

Contract-bound handles (created via definePackageContract(...).capability(...)) are namespaced by their owning contract so two contracts that pick the same short name (e.g. both slingshot-assets and slingshot-search exposing a runtime capability) don’t collide. Free-floating handles created via defineCapability(...) keep their legacy name key.

function capabilityProviderKey(handle: PackageCapabilityHandle<unknown>): string

Source: packages/slingshot-core/src/packageAuthoring.ts

Capture immutable identity for transport across an asynchronous boundary.

function captureTenantExecutionContext(input: TenantExecutionContextInput,): TenantExecutionContextSnapshot

Source: packages/slingshot-core/src/context/tenantExecutionContext.ts

Create a console-backed JSON logger. Each call emits a single JSON line via the console method matching the level (console.debug, console.info, console.warn, console.error). Lines below the configured level are suppressed.

function createConsoleLogger(opts?: { level?: LogLevel; base?: LogFields }): Logger

Source: packages/slingshot-core/src/observability/logger.ts

Create a CoreRegistrar / drain pair for collecting auth-boundary dependencies during the plugin lifecycle before they are committed to the SlingshotContext.

The auth plugin calls registrar.set* and registrar.add* methods during its setupPost phase. createApp() then calls drain() to snapshot all registered values and write them immutably into the SlingshotContext.

Remarks: Closure semantics: all mutable state (routeAuth, actorResolver, etc.) is owned by the closure created by createCoreRegistrar(). The registrar object holds references to setter functions that mutate this closure state. This is intentional — no module-level singletons, no shared state between app instances.

Remarks: Drain idempotency: drain() can be called multiple times safely. Each call returns a new CoreRegistrarSnapshot object with a snapshot of the current closure state at call time. The first drain() seals the registrar against any further mutation: later set* / add* calls throw so plugins cannot continue mutating bootstrap-owned framework dependencies after finalization. In practice, createApp() calls drain() exactly once, after all setupPost hooks have completed.

Remarks: Call createCoreRegistrar() once per createApp() invocation — never share a registrar across app instances.

function createCoreRegistrar(): void

Source: packages/slingshot-core/src/coreRegistrar.ts

Creates a default FingerprintBuilder that produces a 6-byte SHA-256 hash of stable browser headers (User-Agent, Accept-Language, Accept-Encoding).

Used as a lightweight bot/request fingerprint when no authenticated user is present. The hash is a 12-character hex string derived from the first 6 bytes of the digest.

Remarks: Headers can be spoofed — this fingerprint is a soft signal, not a security guarantee. The auth plugin may replace this with a richer implementation (e.g., one that incorporates IP, TLS fingerprint, or cookie entropy).

function createDefaultFingerprintBuilder(): FingerprintBuilder

Source: packages/slingshot-core/src/defaults/defaultFingerprint.ts

Default resolver. Selection order:

  • If userId is set, the actor is a 'user'.
  • If only apiKeyId is set, the actor is an 'api-key'.
  • If only serviceAccountId is set, the actor is a 'service-account'.
  • Otherwise, the actor is 'anonymous' (with tenantId carried through).
function createDefaultIdentityResolver(): IdentityResolver

Source: packages/slingshot-core/src/identity.ts

Build the default authorizeSubscriber predicate for a definition, allowing delivery only when the event has external exposure and the subscriber matches the envelope’s scope.

function createDefaultSubscriberAuthorizer<K extends EventKey>(definition: Pick<EventDefinition<K>, 'exposure'>,): EventSubscriberAuthorizer<K>

Source: packages/slingshot-core/src/eventDefinition.ts

Create a new entity registry with closure-owned state.

Each createApp() call produces its own registry instance — no module-level singletons, no shared mutable state between app instances.

Remarks: Frozen configs at registration time: each ResolvedEntityConfig is frozen with Object.freeze() when passed to register. This prevents plugins from mutating entity configs after they have been registered and ensures that getAll() / filter() callers always see the original, immutable config. Deep sub-objects are not frozen by this call — only the top-level config object is frozen.

Remarks: Duplicate detection: uniqueness is enforced on the (name, namespace) tuple. Two entities with the same name in different namespaces are considered distinct. Attempting to register a duplicate throws immediately at bootstrap time so the misconfiguration is visible as a startup error rather than a silent override.

function createEntityRegistry(): EntityRegistry

Source: packages/slingshot-core/src/entityRegistry.ts

Create an EventDefinitionRegistry with closure-owned state that validates and freezes each definition on registration and rejects duplicates or post-freeze writes.

function createEventDefinitionRegistry(options: EventDefinitionRegistryOptions = {},): EventDefinitionRegistry

Source: packages/slingshot-core/src/eventDefinitionRegistry.ts

Create a deep-frozen EventEnvelope from the given parameters.

Generates a unique eventId (UUID v4) and an ISO-8601 occurredAt timestamp. The returned envelope and all nested objects are recursively frozen to prevent downstream mutation.

function createEventEnvelope<K extends EventKey>(params: CreateEventEnvelopeParams<K>,): EventEnvelope<K>

Source: packages/slingshot-core/src/eventEnvelope.ts

Create a SlingshotEvents instance backed by a definition registry and event bus.

The returned publisher validates payloads against the definition’s Zod schema, resolves event scope via the definition’s resolveScope, wraps the result in a deep-frozen EventEnvelope, and emits it through the provided bus.

function createEventPublisher(options: CreateEventPublisherOptions): SlingshotEvents

Source: packages/slingshot-core/src/eventPublisher.ts

Creates a new event schema registry instance.

function createEventSchemaRegistry(): EventSchemaRegistry

Source: packages/slingshot-core/src/eventSchemaRegistry.ts

Create an instance-scoped registry for explicit, ascending event payload migrations.

Each adapter must advance exactly one version. This makes replay paths unique, prevents accidental downgrade/cycles, and surfaces missing compatibility work before an operator mutates durable outbox state.

function createEventVersionRegistry(): EventVersionRegistry

Source: packages/slingshot-core/src/eventVersionRegistry.ts

Create a throttled expired-entry eviction function for use with in-memory stores.

Each call returns an independent eviction function with closure-owned state — no shared module-level state between instances. The eviction function scans the provided Map for entries whose expiresAt has passed, removing them. The O(n) scan is throttled to run at most once per intervalMs to avoid performance degradation on high-frequency write paths.

Call this once inside the factory that creates the in-memory store, then call the returned function on each write to trigger periodic cleanup.

Remarks: The returned function only prevents the map from growing unboundedly — individual reads should still check expiresAt at point-in-time to avoid serving stale values between scan intervals.

function createEvictExpired(intervalMs = EVICTION_INTERVAL_MS,): <K, V extends

Source: packages/slingshot-core/src/memoryEviction.ts

Factory function that creates a new InProcessAdapter instance.

Prefer this over new InProcessAdapter() in application code — it returns the SlingshotEventBus interface rather than the concrete class, keeping the call site decoupled from the implementation.

Remarks: Each call returns a fully independent instance — listeners, pending handlers, and the listener registrations and pending handler sets are all owned by the returned object and never shared. Calling createInProcessAdapter() twice produces two completely isolated buses.

function createInProcessAdapter(serializationOpts?: EventBusSerializationOptions,): SlingshotEventBus

Source: packages/slingshot-core/src/eventBus.ts

Create an in-process MetricsEmitter that aggregates counters, gauges, and timings into a memory-resident snapshot.

Aggregation rules:

  • Counters add — repeated calls with the same name+labels accumulate.
  • Gauges are last-write-wins — only the most recent value is retained.
  • Timings record into a bounded reservoir (RESERVOIR_LIMIT samples per series). Snapshots derive p50/p95/p99 + count/sum/min/max from the reservoir at read time.

Designed for tests and single-instance deployments. For production, prefer a backend-specific emitter (Prometheus, OTel) so metrics survive process restarts and can be aggregated across instances.

function createInProcessMetricsEmitter(logger?: Logger): InProcessMetricsEmitter

Source: packages/slingshot-core/src/metrics.ts

Creates an in-memory CacheAdapter backed by a Map with TTL support.

Supports get, set (with optional TTL in seconds), del, and glob delPattern. Entries expire on get (point-in-time check) and are periodically swept by evictExpired. Store size is capped at DEFAULT_MAX_ENTRIES.

Remarks: This adapter is not distributed. For production multi-instance deployments, use a Redis-backed cache adapter registered via the auth or cache plugin.

function createMemoryCacheAdapter(): CacheAdapter

Source: packages/slingshot-core/src/defaults/memoryCacheAdapter.ts

In-memory adapter for tests and single-instance deployments.

Uses simple FIFO eviction once maxEntries is reached.

Remarks: This adapter stores idempotency state in process memory only. For production multi-instance deployments, use a durable adapter backed by a shared store (e.g. Redis, Postgres).

function createMemoryOperationIdempotencyAdapter(opts?: { defaultTtlMs?: number; maxEntries?: number; }): IdempotencyAdapter

Source: packages/slingshot-core/src/idempotency/index.ts

Creates an in-memory rate limit adapter backed by a Map.

Tracks request counts per key in a rolling time window. The window resets when the current time exceeds resetAt — there is no sliding window; each key gets a fixed-duration bucket that resets on the first request after expiry.

Remarks: Not suitable for multi-instance or distributed deployments. Rate limit counts are held entirely in the process heap — no synchronisation with other server instances occurs. In a horizontally-scaled deployment each instance enforces its own independent limit, so the effective per-user limit becomes max × instanceCount. For production deployments with more than one server process, replace this adapter with a Redis-backed implementation via ctx.registrar.setRateLimitAdapter(...) in the auth plugin.

Remarks: Map eviction strategy: On every trackAttempt, expired entries (those whose resetAt has passed) are swept first so they do not consume capacity. If the store is still over DEFAULT_MAX_ENTRIES after sweeping, the oldest entries by insertion order are evicted. This bounds memory use while protecting valid entries from being evicted by stale or attacker-generated keys.

Remarks: Production warning: this adapter is registered as the framework default so the server starts without requiring an auth plugin. Replace it in any deployment that expects non-trivial traffic or has security requirements around rate limiting.

function createMemoryRateLimitAdapter(): RateLimitAdapter

Source: packages/slingshot-core/src/defaults/memoryRateLimit.ts

Create a no-op MetricsEmitter.

Used as the default when the host application has not configured a metrics backend. Every method is a constant-time no-op so callers can emit unconditionally without checking for a configured emitter first.

function createNoopMetricsEmitter(): MetricsEmitter

Source: packages/slingshot-core/src/metrics.ts

Create the guarded plugin-state map used by framework app contexts.

function createPluginStateMap(entries?: Iterable<readonly [string, unknown]>,): PluginStateMap

Source: packages/slingshot-core/src/pluginState.ts

Create a PostgresPoolRuntime that accumulates query-count, error, and duration metrics for a pool.

function createPostgresPoolRuntime(opts?: { migrationMode?: PostgresMigrationMode; healthcheckTimeoutMs?: number; }): PostgresPoolRuntime

Source: packages/slingshot-core/src/postgresRuntime.ts

Create an envelope for system-internal emissions with no originating request context.

Used by the raw bus emit() path when events are fired outside a request lifecycle. The envelope has 'internal' exposure, null scope, 'system' source, and no requestId or correlationId (both will be undefined).

function createRawEventEnvelope<K extends EventKey>(key: K, payload: SlingshotEventMap[K],): EventEnvelope<K>

Source: packages/slingshot-core/src/eventEnvelope.ts

Drop-in replacement for createRoute from @hono/zod-openapi.

Automatically registers unnamed request body and response schemas as named OpenAPI components so they appear in components/schemas instead of being inlined at every use site. Generated names follow the convention:

{Method}{PathSegments}Request {Method}{PathSegments}{Status}

Schemas already named via .openapi("Name") are never overwritten.

function createRoute<T extends RouteConfig>(config: T): T

Source: packages/slingshot-core/src/createRoute.ts

Create a new OpenAPIHono router pre-configured with the Slingshot AppEnv type and the shared defaultHook for validation error handling.

All plugin and framework routes use this factory so that error formatting and context variable typing are consistent across the entire application.

Remarks: Use createRouter() (not new Hono() or new OpenAPIHono()) for any router that: - Declares OpenAPI routes via router.openapi(createRoute(...), handler) - Needs access to typed AppVariables (requestId, tenantId, slingshotCtx, etc.) - Should participate in the shared defaultHook validation error pipeline

Remarks: A plain new Hono() is acceptable for middleware-only routers that never call c.get('slingshotCtx') or declare OpenAPI routes.

function createRouter(): void

Source: packages/slingshot-core/src/context.ts

Creates a multiplexing SlingshotEventBus that routes each event to the appropriate backing adapter based on longest-prefix namespace matching.

emit, on, and off are each forwarded to the single adapter that owns the event’s namespace. shutdown is forwarded to every adapter.

Remarks: Use this when you need different backing stores per event domain — for example, community events in a Redis Streams adapter for fan-out, while security events stay in-process. Listeners registered before createRouterAdapter is called are attached to the individual adapters, not the router — the router is a dispatch layer only.

function createRouterAdapter(opts: RouterAdapterOptions): SlingshotEventBus

Source: packages/slingshot-core/src/routerAdapter.ts

Create a fetch-compatible function that resolves DNS once, validates the resolved IP, and pins the underlying TCP connection to that IP. This closes the DNS-rebinding TOCTOU window present in plain fetch, which re-resolves the hostname inside the HTTP client after caller-side validation.

function createSafeFetch(opts: SafeFetchOptions = {}): typeof fetch

Source: packages/slingshot-core/src/http/safeFetch.ts

Create an isolated, duplicate-safe boundary registry for one app instance.

function createTenantBoundaryRegistry(): TenantBoundaryRegistry

Source: packages/slingshot-core/src/tenantBoundaries.ts

Create an explicit manager for infrastructure that supports no rollback transactions.

Manual repository fixtures can use this helper to satisfy StoreInfra without accidentally claiming that a configured client provides framework transaction semantics.

function createUnsupportedTransactionManager(): TransactionManager

Source: packages/slingshot-core/src/transactions.ts

Build a Zod schema for a standard cursor-paginated response envelope and register it in components/schemas under name.

The schema wraps an array of itemSchema with an optional nextCursor field.

function cursorPaginatedResponse<T extends ZodType>(itemSchema: T, name: string): void

Source: packages/slingshot-core/src/pagination.ts

Build a Zod schema for cursor-based pagination query parameters (limit, cursor).

function cursorParams(defaults?: CursorParamDefaults): void

Source: packages/slingshot-core/src/pagination.ts

Decode a base64 cursor string back to its typed payload.

Returns null if the cursor is malformed (invalid base64 or non-JSON). When a validate type guard is provided, the decoded value is checked at runtime and null is returned if it fails the guard.

function decodeCursor<T extends object>(cursor: string, validate?: (parsed: unknown) => parsed is T,): T | null

Source: packages/slingshot-core/src/cursor.ts

Decrypt a value encrypted by encryptField.

Parses the ciphertext envelope to find the keyId, locates the matching DEK in keyConfig, then decrypts using AES-256-GCM. Supports key rotation — any valid key in keyConfig can decrypt, not just the first.

function decryptField(ciphertext: string, keyConfig: DataEncryptionKey[]): string

Source: packages/slingshot-core/src/crypto.ts

Recursively freezes an object and all of its nested plain-object values.

Remarks: Deep vs shallow: Object.freeze is inherently shallow — it only prevents top-level property mutations. deepFreeze recurses into all enumerable own values that are non-null objects and not already frozen. This means nested config objects (e.g., config.sessionPolicy, config.mfa) are also immutable after the call.

Remarks: Frozen objects throw TypeError on mutation attempts in strict mode (all TypeScript modules) and silently ignore mutations in sloppy mode.

Remarks: Arrays and class instances embedded in the value tree are also frozen if encountered during the traversal. Primitive values (string, number, boolean) are skipped.

Remarks: Caution: Do not deep-freeze config objects that hold mutable runtime references (e.g., database adapters, permission adapters). Use Object.freeze() (shallow) for those instead.

function deepFreeze<T>(value: T): T

Source: packages/slingshot-core/src/deepFreeze.ts

The Hono defaultHook used by all OpenAPIHono routers created via createRouter().

Intercepts Zod validation failures from @hono/zod-openapi and returns a structured 400 response using the request’s configured validationErrorFormatter. Falls back to defaultValidationErrorFormatter if the formatter throws.

Remarks: If the custom validationErrorFormatter itself throws (e.g., due to a bug in a user’s formatter), defaultHook silently catches the error and retries with defaultValidationErrorFormatter. This means a broken custom formatter will degrade to the default shape rather than producing an unhandled 500 error.

Source: packages/slingshot-core/src/context.ts

The built-in Zod validation error formatter used by defaultHook.

Produces { error, details, requestId } where details is a per-field breakdown. Assign config.validationErrorFormatter in your app config to replace this with a custom formatter that matches your API’s error contract.

Remarks: This function never throws. It is also the automatic fallback inside defaultHook when a custom ValidationErrorFormatter throws — so overriding it is safe to do without worrying about breaking the fallback path.

Source: packages/slingshot-core/src/context.ts

Declare a named typed capability that packages can publish and require explicitly.

function defineCapability<TValue>(name: string): PackageCapabilityHandle<TValue>

Source: packages/slingshot-core/src/packageAuthoring.ts

Declare a typed, validated config namespace.

function defineConfig<S extends z.ZodObject>(spec: { readonly namespace: string; readonly schema: S; readonly source?: ConfigSource; }): ConfigDefinition<z.infer<S>>

Source: packages/slingshot-core/src/config.ts

Build a validated, frozen EventDefinition from a key and its definition body.

function defineEvent<K extends EventKey>(key: K, definition: Omit<EventDefinition<K>, 'key' | 'schemaVersion'> & { readonly schemaVersion?: number; },): Readonly<EventDefinition<K>>

Source: packages/slingshot-core/src/eventDefinition.ts

Define a transport-agnostic handler.

Returns a frozen SlingshotHandler whose SlingshotHandler.invoke method runs the full pipeline: input validation → guards → handle → output validation → after hooks. Guards that carry an _afterHook are automatically collected and appended to the after-hook list.

function defineHandler<TInput extends ZodTypeAny, TOutput extends ZodTypeAny>(config: HandlerConfig<TInput, TOutput>,): SlingshotHandler<TInput, TOutput>

Source: packages/slingshot-core/src/handler.ts

Declare a health indicator. This is a typed identity helper — it doesn’t register anything by itself; the indicator must be passed to defineApp({ health: { indicators: [...] } }) to take effect.

Returns the input frozen and unchanged so callers can pass it through any config pipeline.

function defineHealthIndicator(indicator: HealthIndicator): HealthIndicator

Source: packages/slingshot-core/src/observability/health.ts

Canonical top-level code-first authoring surface for packages.

function definePackage(input: DefinePackageInput): SlingshotPackageDefinition

Source: packages/slingshot-core/src/packageAuthoring.ts

Declare a provider-owned package public contract. The returned object owns the package’s typed public surface — capabilities and public entity refs — and gates definePackage(...) so capability ownership and dependency wiring can be validated at authoring time.

function definePackageContract<const TName extends string>(contractName: TName,): PackageContract<TName>

Source: packages/slingshot-core/src/packageAuthoring.ts

Define a typed plugin-state key.

function definePluginStateKey<T>(name: string): PluginStateKey<T>

Source: packages/slingshot-core/src/pluginState.ts

Define a typed (key, resolver) policy token.

The returned token can be passed directly to registerEntityPolicy(...) and referenced in EntityRoutePolicyConfig.resolver — the framework uses token.key for the lookup and registration, so the same value in both places guarantees consistency.

function definePolicy<TRecord = unknown, TInput = unknown>(key: string, resolver: PolicyResolver<TRecord, TInput>,): PolicyToken<TRecord, TInput>

Source: packages/slingshot-core/src/entityRouteConfig.ts

Declare a request scope. This is a typed identity helper — it doesn’t register anything by itself. Pass the result to defineApp({ requestScopes: [...] }) to wire it into the request lifecycle.

function defineRequestScope<T>(spec: { readonly name: string; readonly factory: (context: RequestScopeContext) => T | Promise<T>; readonly cleanup?: (value: T, context: RequestScopeContext) => void | Promise<void>; }): RequestScope<T>

Source: packages/slingshot-core/src/requestScope.ts

Parse and validate a serialized tenant execution context envelope.

function deserializeTenantExecutionContext(value: unknown): TenantExecutionContextSnapshot

Source: packages/slingshot-core/src/context/tenantExecutionContext.ts

Build the standard disableRoutes Zod field for a plugin config schema.

Produces a z.array(z.enum([...values])) schema that validates the disableRoutes array in a plugin config. Pass Object.values(MY_ROUTES) as the allowed values.

function disableRoutesSchema<T extends string>(values: readonly T[]): void

Source: packages/slingshot-core/src/configValidation.ts

Emit the generated warning policy for a declared package from a public factory call.

function emitConfiguredPackageStabilityWarning(packageName: keyof typeof PACKAGE_MATURITY, detail?: string,): void

Source: packages/slingshot-core/src/stability.ts

Emit a standard Node/Bun runtime warning once per package stability label.

Use this from public factory functions in packages that are not yet stable. The warning is deduplicated per package name and stability label so repeated calls do not spam logs.

function emitPackageStabilityWarning(packageName: string, stability: Exclude<PackageStability, 'stable'>, detail?: string,): void

Source: packages/slingshot-core/src/stability.ts

Encode a cursor payload as a URL-safe base64 string.

Serialises payload as JSON then base64-encodes it using btoa. The result is an opaque string safe to include in query parameters without URL encoding. Reverse with decodeCursor.

function encodeCursor(payload: object): string

Source: packages/slingshot-core/src/cursor.ts

Encrypt a plaintext string field with AES-256-GCM.

Uses the first key in keyConfig to encrypt. Generates a random 96-bit IV per call so identical plaintexts produce different ciphertexts.

function encryptField(plaintext: string, keyConfig: DataEncryptionKey[]): string

Source: packages/slingshot-core/src/crypto.ts

Runtime-complete capability ordering used by profiles, reports, and docs.

Source: packages/slingshot-core/src/entityCapabilities.ts

Runtime-complete list of declarative entity operation discriminants.

Keep this list exhaustive with OperationConfig. Backend capability profiles, conformance registration, and generated documentation all consume this value so a new operation cannot exist only at the type level.

Source: packages/slingshot-core/src/operations.ts

Zod schema for validating an EntityChannelConfig input at runtime.

Used by plugin bootstrap and validateEntityChannelConfig to catch misconfigured WebSocket channel declarations before server startup. Enforces that channels is a non-empty record and that all sub-schemas conform to their expected shapes.

Source: packages/slingshot-core/src/entityChannelConfigSchema.ts

Create a typed entity ref that can be used outside the owning package.

Pass a local entity module for same-package typed lookups, or attach plugin when exporting a ref for another package to consume.

function entityRef<TAdapter>(entity: SlingshotPackageEntityModuleLike<TAdapter>, options?: { plugin?: string },): PackageEntityRef<TAdapter>; /** * Create a typed entity ref directly from a package/entity name pair. * * @deprecated For cross-package entity access, prefer publishing a typed ref through a * package contract: `Matches.publicEntities(

Source: packages/slingshot-core/src/packageAuthoring.ts

Zod schema for validating an EntityRouteConfig input at runtime.

Used by plugin bootstrap and the validateEntityRouteConfig helper to catch misconfigured entity route declarations early, before server startup. Pass any raw config object (from JSON, YAML, or untyped module exports) to get structured Zod errors rather than opaque runtime failures.

Remarks: Forbidden event key namespaces (security., auth:, community:delivery., push:, app:) are enforced by the inline eventKeySchema applied to every event key field across create, get, list, update, delete, and operations entries. Any event key using a forbidden prefix causes validation to fail with a descriptive Zod issue. Rate limit fields (windowMs, max) must be positive integers — zero and negative values are rejected. The retention.hardDelete.after duration string must match {positive integer}{s|m|h|d|w|y} (e.g. '90d', '1y').

Source: packages/slingshot-core/src/entityRouteConfigSchema.ts

Build a consistent JSON error response that always includes requestId.

Replaces the common c.json({ error: '…' }, status) pattern so every error the client sees carries the request-id for support/debugging.

function errorResponse<E extends AppEnv, S extends ErrorStatus>(c: Context<E>, message: string, status: S,): void

Source: packages/slingshot-core/src/errorResponse.ts

Evaluate the effective authenticated-user access policy exposed by auth.

Built-in checks remain the default baseline:

  • suspended accounts are denied
  • required email verification is enforced for email-primary apps

When auth publishes evaluateUserAccess, that user-defined policy runs after the built-ins and can impose additional restrictions without teaching core about application-specific account-state fields.

async function evaluateAuthUserAccess(runtime: AuthRuntimePeer, input: AuthUserAccessInput,): Promise<AuthUserAccessDecision>

Source: packages/slingshot-core/src/authPeer.ts

Evaluate a FilterExpression against a record.

Supports field equality, comparison operators ($gt, $gte, $lt, $lte, $ne), set operators ($in, $nin), substring matching ($contains), logical composition ($and, $or), 'param:x' runtime references, and the 'now' date sentinel.

Remarks: Performance note: evaluateFilter is a pure runtime interpreter — it walks the filter expression tree on every call with no compilation or caching step. This is intentional for in-memory adapters and tests, where datasets are small and startup cost matters more than throughput. For production storage backends (Postgres, Mongo, Redis), filter predicates should be translated into native queries at the adapter layer rather than fetching all records and filtering here. Use the codegen counterpart in slingshot-data/generators/filter.ts when you need compiled filter predicates.

Remarks: Logical short-circuiting: field conditions are evaluated first, then $and, then $or. Evaluation stops as soon as a false result is found, matching standard short-circuit semantics. $and and $or sub-expressions may themselves be recursive.

function evaluateFilter(record: Record<string, unknown>, filter: FilterExpression, params: Record<string, unknown> = {},): boolean

Source: packages/slingshot-core/src/filterEvaluator.ts

Return whether a definition declares any exposure that delivers events outside the framework (client-safe, tenant/user/app webhooks, or connectors).

function eventHasExternalExposure<K extends EventKey>(definition: Pick<EventDefinition<K>, 'exposure'>,): boolean

Source: packages/slingshot-core/src/eventDefinition.ts

Evict the oldest entries from a Map when it exceeds maxEntries.

JavaScript Map iterates in insertion order, so the entries deleted from the front are always the oldest. Useful for capping memory store size in development and single-process deployments.

function evictOldest<K, V>(map: Map<K, V>, maxEntries: number): void

Source: packages/slingshot-core/src/memoryEviction.ts

Evict the oldest entries from an Array when it exceeds maxEntries.

Splices from the front (index 0), assuming the array is ordered oldest-first. Used for fixed-size append-only arrays like password history.

function evictOldestArray(arr: unknown[], maxEntries: number): void

Source: packages/slingshot-core/src/memoryEviction.ts

Extract all 'param:x' parameter names referenced in a filter expression.

Use this to determine which runtime parameter keys need to be resolved before calling evaluateFilter. Returns a deduplicated array.

function extractFilterParams(filter: FilterExpression): string[]

Source: packages/slingshot-core/src/filterEvaluator.ts

Extract 'param:x' parameter names from a match record (e.g., for transition or lookup ops).

A match record maps entity field names to 'param:x' references or literal values. Returns only the parameter names (not literal values).

function extractMatchParams(match: Record<string, string | number | boolean>): string[]

Source: packages/slingshot-core/src/filterEvaluator.ts

Extract user IDs from <@userId> tokens in body text.

Used as a fallback when the client does not provide a mentions[] array. Skips tokens inside code blocks and code spans.

function extractMentionsFromBody(body: string): readonly string[]

Source: packages/slingshot-core/src/contentParser.ts

The field builder namespace — the only way to create FieldDef values for use in EntityConfig.fields.

Each method returns a typed FieldDef with sensible defaults. Pass FieldOptions to control optionality, defaults, immutability, and primary key status.

Source: packages/slingshot-core/src/entityConfig.ts

Generate a JSON-serializable example for documentation / OpenAPI specs.

Uses seed 42 and 100% optional rate so output is deterministic and includes all fields. Strips undefined values.

function generateExample<T>(schema: { _zod: { def: { type: string } } }, overrides?: Record<string, unknown>,): T

Source: packages/slingshot-core/src/faker/generateFromSchema.ts

Generate a single fake value that conforms to the given Zod schema.

Works with any Zod 4 schema — objects, primitives, arrays, unions, enums, pipes, intersections, lazy schemas, etc. Format-aware: a z.string().email() produces a realistic email, z.string().uuid() produces a UUID, and so on.

function generateFromSchema<T>(schema: { _zod: { def: { type: string } } }, opts: GenerateOptions = {},): T

Source: packages/slingshot-core/src/faker/generateFromSchema.ts

Generate multiple fake values for a given schema.

function generateMany<T>(schema: { _zod: { def: { type: string } } }, count: number, opts: GenerateOptions = {},): T[]

Source: packages/slingshot-core/src/faker/generateFromSchema.ts

Generates a cryptographically secure random token with 256 bits of entropy.

Returns a base64url-encoded string (43 characters, no padding). Suitable for session IDs, refresh tokens, and any secret that must resist brute-force guessing over long time windows (e.g. 30-day refresh tokens).

Replaces crypto.randomUUID() (122-bit UUIDv4) where OWASP recommends ≥128 bits for session identifiers.

function generateSecureToken(): string

Source: packages/slingshot-core/src/crypto.ts

Resolve the canonical actor for a Hono request context.

Reads the actor variable published by the auth middleware (identify, bearerAuth, or a custom identity middleware). Returns ANONYMOUS_ACTOR when no actor has been published.

function getActor(c: Context<AppEnv>): Actor

Source: packages/slingshot-core/src/actorContext.ts

Resolve the current actor ID from request context.

Returns null for anonymous requests.

function getActorId(c: Context<AppEnv>): string | null

Source: packages/slingshot-core/src/actorContext.ts

Resolve the current actor tenant scope from request context.

Returns null for tenantless actors and single-tenant requests.

function getActorTenantId(c: Context<AppEnv>): string | null

Source: packages/slingshot-core/src/actorContext.ts

Retrieve the auth runtime peer from plugin state.

function getAuthRuntimePeer(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): AuthRuntimePeer

Source: packages/slingshot-core/src/authPeer.ts

Retrieve the auth runtime peer from plugin state when auth has published it.

function getAuthRuntimePeerOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): AuthRuntimePeer | null

Source: packages/slingshot-core/src/authPeer.ts

Retrieve the CacheAdapter registered for a named store on a Slingshot app or context instance.

The framework supports multiple cache backends per app (redis, memory, sqlite, etc.). Each store is registered separately and retrieved by its CacheStoreName key. Use this in framework internals and plugins that need to cache responses or state.

function getCacheAdapter(input: ContextCarrier, store: CacheStoreName): CacheAdapter

Source: packages/slingshot-core/src/cache.ts

Retrieve the CacheAdapter for a named store, returning null if not registered.

Use this when the cache adapter is optional and you want to handle the missing-adapter case gracefully without catching an error. This is the null-safe companion to getCacheAdapter — prefer it in plugin code where cache support is opt-in and the calling path must degrade gracefully when no adapter is configured.

Remarks: Unlike getCacheAdapter, this function never throws. It returns null whenever the adapter is absent, letting the caller decide whether to skip caching or fall back to a default behaviour. Only use getCacheAdapter (the throwing variant) when the adapter is unconditionally required and its absence represents a configuration error.

function getCacheAdapterOrNull(input: ContextCarrier, store: CacheStoreName,): CacheAdapter | null

Source: packages/slingshot-core/src/cache.ts

Extract the real client IP address from a Hono request context.

When trustProxy is false (the default), returns the raw socket address. When trustProxy is a number N, reads the Nth entry from the right of the X-Forwarded-For header chain, then falls back to X-Real-IP, then the socket address.

IPv4-mapped IPv6 addresses (::ffff:1.2.3.4) are normalised to plain IPv4. Returns 'unknown' if no address is available.

Remarks: The trustProxy setting is read from SlingshotContext (if available on the context variable slingshotCtx) or from the symbol attached by setStandaloneTrustProxy. Never trust X-Forwarded-For headers if your server is directly internet-facing — clients can spoof them to bypass IP-based rate limiting.

Remarks: IPv6-mapped IPv4 normalisation: addresses in the form ::ffff:1.2.3.4 (IPv4 mapped into the IPv6 address space) are automatically normalised to plain IPv4 notation (1.2.3.4). This affects the socket IP, the X-Forwarded-For entries, and the X-Real-IP value — all are normalised before being returned. The normalisation is purely cosmetic and does not affect routing or security semantics.

function getClientIp<E extends AppEnv>(c: Context<E>): string

Source: packages/slingshot-core/src/clientIp.ts

Extract the real client IP address from a raw Request.

Reads the socket IP snapshot attached by setStandaloneClientIp, then applies the same trustProxy semantics as getClientIp.

function getClientIpFromRequest(req: Request, trustProxy: false | number): string

Source: packages/slingshot-core/src/clientIp.ts

Retrieve the SlingshotContext for a Hono app instance.

The context is attached by createApp() after all plugins have been initialised. Use this in plugin setupPost hooks and in application code outside request handlers (e.g., job workers, CLI commands, shutdown hooks).

function getContext(app: object): SlingshotContext

Source: packages/slingshot-core/src/context/contextStore.ts

Retrieve the SlingshotContext for a Hono app instance, or null if not attached.

Use this when context availability is optional — for example, in standalone plugin setup that may run before or without a full createApp() call.

function getContextOrNull(app: object): SlingshotContext | null

Source: packages/slingshot-core/src/context/contextStore.ts

Retrieve a single email template by key from a Slingshot app or context instance.

Remarks: Returns null (not undefined) when the key is absent, for consistent null-checking. A null result means the template was never registered — either the plugin that provides it is not installed, or the key name is incorrect. Always guard with a null-check before using the result.

function getEmailTemplate(input: ContextCarrier, key: string): EmailTemplate | null

Source: packages/slingshot-core/src/emailTemplates.ts

Retrieve all email templates registered on a Slingshot app or context instance.

Templates are registered by plugins during setupPost via ctx.registrar.addEmailTemplates(...). Returns a plain object snapshot of all registered templates keyed by template name.

Remarks: The returned object is a snapshot — a new plain object is created from the internal ReadonlyMap on every call. Mutating the returned object does not affect the registered templates. If you need to check for a single template, prefer getEmailTemplate() (which reads directly from the map without a full snapshot).

function getEmailTemplates(input: ContextCarrier): Record<string, EmailTemplate>

Source: packages/slingshot-core/src/emailTemplates.ts

Resolve the EmbedsPeer from plugin state, throwing if the embeds plugin is not registered.

function getEmbedsPeer(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): EmbedsPeer

Source: packages/slingshot-core/src/embedsPeer.ts

Resolve the EmbedsPeer from plugin state, returning null if the embeds plugin is not available.

function getEmbedsPeerOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): EmbedsPeer | null

Source: packages/slingshot-core/src/embedsPeer.ts

Retrieve the FingerprintBuilder registered on a Slingshot app or context instance.

The fingerprint builder produces a short hash of stable request headers (User-Agent, Accept-Language, Accept-Encoding) to assist bot detection and rate limiting when no authenticated user is present. The default is createDefaultFingerprintBuilder().

Remarks: The default fingerprint builder hashes stable, non-identifying request headers (User-Agent, Accept-Language, Accept-Encoding) to produce a short opaque token suitable for rate limiting unauthenticated traffic. It does NOT uniquely identify individual users — it groups requests by device/browser profile. The auth plugin may replace it with a more sophisticated implementation that incorporates IP address or TLS fingerprint signals.

function getFingerprintBuilder(input: ContextCarrier): FingerprintBuilder

Source: packages/slingshot-core/src/rateLimit.ts

Resolve PermissionsState from plugin state.

Throws when slingshot-permissions has not published either its contract capabilities or its legacy runtime state.

function getPermissionsState(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PermissionsState

Source: packages/slingshot-core/src/permissions.ts

Resolve PermissionsState from plugin state when the permissions plugin is present.

Reads the three capabilities (evaluator, registry, adapter) published by slingshot-permissions through its Permissions package contract. Returns null when any of them is unavailable, so optional integrations can fail closed without inspecting raw map entries themselves.

For typed cross-package access prefer ctx.capabilities.require(PermissionsEvaluatorCap) etc. directly — this helper exists for the convenience of consumers that want the combined { evaluator, registry, adapter } shape in one call.

function getPermissionsStateOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PermissionsState | null

Source: packages/slingshot-core/src/permissions.ts

Resolve a PluginStateMap from the given input, throwing when unavailable.

Behaves identically to getPluginStateOrNull but throws instead of returning null. Use this when plugin state is required for correct operation.

function getPluginState(input: PluginStateMap | PluginStateCarrier | object,): PluginStateMap

Source: packages/slingshot-core/src/pluginState.ts

Read the PluginStateMap from a Hono request context variable, throwing when unavailable.

Behaves identically to getPluginStateFromRequestOrNull but throws instead of returning null. Use this inside route handlers where plugin state is guaranteed to be present.

function getPluginStateFromRequest(c: { get(key: string): unknown }): PluginStateMap

Source: packages/slingshot-core/src/pluginState.ts

Read the PluginStateMap from a Hono request context variable.

Looks up c.get('slingshotCtx') and resolves plugin state from the resulting carrier. Returns null when the context variable is absent.

function getPluginStateFromRequestOrNull(c: { get(key: string): unknown; }): PluginStateMap | null

Source: packages/slingshot-core/src/pluginState.ts

Resolve a PluginStateMap from the given input, falling back to the ambient SlingshotContext when the input is a plain object that does not directly carry plugin state.

function getPluginStateOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PluginStateMap | null

Source: packages/slingshot-core/src/pluginState.ts

Extract the registry lookup key from an EntityRoutePolicyConfig.resolver value.

Accepts the legacy string form or a typed PolicyToken and returns the canonical string key used by the policy registry.

function getPolicyResolverKey(resolver: string | PolicyTokenRef): string

Source: packages/slingshot-core/src/entityRouteConfig.ts

Retrieve the PostgresPoolRuntime previously attached to a pool, or null if none.

function getPostgresPoolRuntime(pool: object): PostgresPoolRuntime | null

Source: packages/slingshot-core/src/postgresRuntime.ts

Resolve a PublishedInteractionsPeer from the given plugin’s state slot, returning null if absent or malformed.

function getPublishedInteractionsPeerOrNull<TPeer extends PublishedInteractionsPeer>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, pluginKey: string,): TPeer | null

Source: packages/slingshot-core/src/publishedInteractionsPeer.ts

Resolve the PushFormatterPeer from plugin state, throwing if the push package is not registered.

function getPushFormatterPeer(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PushFormatterPeer

Source: packages/slingshot-core/src/pushPeer.ts

Resolve the PushFormatterPeer from plugin state, returning null when the push package is unavailable.

function getPushFormatterPeerOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PushFormatterPeer | null

Source: packages/slingshot-core/src/pushPeer.ts

Retrieve the RateLimitAdapter registered on a Slingshot app or context instance.

The rate limit adapter tracks request counts per key within a rolling window. The framework uses it for endpoint-level rate limiting middleware. The default implementation is createMemoryRateLimitAdapter() (registered by createApp()). The auth plugin may replace it with a distributed (Redis) implementation.

Remarks: A memory-based RateLimitAdapter is always registered by createApp() as the default, so this function should never throw in a correctly bootstrapped Slingshot app. The only way to reach the throw is to call getRateLimitAdapter() on a SlingshotContext that was constructed manually (e.g., in a unit test) without going through createApp().

function getRateLimitAdapter(input: ContextCarrier): RateLimitAdapter

Source: packages/slingshot-core/src/rateLimit.ts

Retrieve the RequestActorResolver registered on a Slingshot app or context instance.

Used by framework internals (WebSocket upgrade, SSE upgrade) to resolve the authenticated actor from the raw Request. The auth plugin registers its resolver during setupPost via ctx.registrar.setRequestActorResolver(...).

Remarks: Error handling: this function throws synchronously with a descriptive message if no resolver is registered. Use it in code paths where a missing resolver is a programming error (e.g., a WebSocket endpoint that requires auth). If the auth plugin is optional in your deployment, use getRequestActorResolverOrNull() instead and handle the null case explicitly to avoid an unhandled exception at runtime.

function getRequestActorResolver(input: ContextCarrier): RequestActorResolver

Source: packages/slingshot-core/src/requestActorResolver.ts

Retrieve the RequestActorResolver registered on a Slingshot app or context instance, returning null if none has been registered.

Use this variant when the auth plugin is optional and you want to handle the missing-resolver case explicitly rather than catching an error.

Remarks: Use case pattern: prefer getRequestActorResolverOrNull() in framework code that conditionally enables auth-gated features (e.g., presence tracking, per-actor rate limiting) only when auth is available:

Remarks: ts const resolver = getRequestActorResolverOrNull(ctx); if (resolver) { const actor = await resolver.resolveActor(req); // enable auth-gated feature } else { // degrade gracefully — no auth plugin installed }

Remarks: For code paths where auth is required and a missing resolver is a bug, use getRequestActorResolver() (throwing variant) instead so the error surfaces at the call site rather than failing silently downstream.

function getRequestActorResolverOrNull(input: ContextCarrier): RequestActorResolver | null

Source: packages/slingshot-core/src/requestActorResolver.ts

Resolve a request-scoped value. Lazily runs the scope’s factory on first call within a given request and returns the cached value on subsequent calls. Throws when called outside an active request (i.e. when the request-scope middleware is not in the middleware chain).

async function getRequestScoped<T>(c: Context, scope: RequestScope<T>): Promise<T>

Source: packages/slingshot-core/src/requestScope.ts

Internal: read the per-request store. Returns undefined when middleware isn’t active.

function getRequestScopeStore(c: Context): RequestScopeStore | undefined

Source: packages/slingshot-core/src/requestScope.ts

Resolve the request-scoped tenant ID from the Hono context.

This is the tenant context set by tenant-resolution middleware (e.g. from a header or subdomain), distinct from getActorTenantId which returns the tenant the actor belongs to. They usually match but can differ for cross-tenant operations.

Returns null in single-tenant mode or when tenant resolution is not active.

function getRequestTenantId(c: Context<AppEnv>): string | null

Source: packages/slingshot-core/src/actorContext.ts

Retrieve the RouteAuthRegistry registered on a Slingshot app or context instance.

The RouteAuthRegistry provides Hono middleware for userAuth, requireRole, and bearerAuth — used by framework-owned routes (jobs, metrics, uploads) when configured with auth: 'userAuth'. The auth plugin registers its registry during setupPost.

function getRouteAuth(input: ContextCarrier): RouteAuthRegistry

Source: packages/slingshot-core/src/routeAuth.ts

Retrieve the RouteAuthRegistry registered on a Slingshot app or context instance, returning null if none has been registered.

function getRouteAuthOrNull(input: ContextCarrier): RouteAuthRegistry | null

Source: packages/slingshot-core/src/routeAuth.ts

Retrieve the search plugin runtime from plugin state.

function getSearchPluginRuntime(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): SearchPluginRuntime

Source: packages/slingshot-core/src/searchPluginRuntime.ts

Retrieve the search plugin runtime from plugin state when search is active.

function getSearchPluginRuntimeOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): SearchPluginRuntime | null

Source: packages/slingshot-core/src/searchPluginRuntime.ts

Retrieve the SlingshotContext from a Hono request context.

The context variable slingshotCtx is set by the framework’s context middleware on every request. Use this in route handlers when you need access to instance-scoped state (persistence, plugins, event bus, secrets, etc.).

Remarks: Timing: safe to call inside any route handler, error handler, or response middleware that runs after the framework’s context middleware. Do NOT call it in constructor-time code, module-level code, or plugin setup phases — slingshotCtx is a per-request variable that only exists within the Hono request pipeline. For access outside a request, use getContext(app) from the framework layer instead.

function getSlingshotCtx(c: Context<AppEnv>): SlingshotContext

Source: packages/slingshot-core/src/context.ts

Hash a token for safe storage — a named alias for sha256.

The plaintext token is what gets sent to the client; the hash is what gets stored. Using a named function makes the intent clear at call sites compared to a raw sha256.

function hashToken(token: string): string

Source: packages/slingshot-core/src/crypto.ts

HMAC-SHA256 sign a string with the active secret.

Accepts either a single secret or a rotated secret array. When an array is provided, the first entry is treated as the active signing key.

function hmacSign(input: string, secret: string | string[]): string

Source: packages/slingshot-core/src/crypto.ts

Convenience builder for compound indexes.

function index(fields: string[], opts?: { direction?: 'asc' | 'desc'; unique?: boolean },): IndexDef

Source: packages/slingshot-core/src/entityConfig.ts

Inspect the effective module graph of a package without reading framework internals.

function inspectPackage(pkg: SlingshotPackageDefinition): PackageInspection

Source: packages/slingshot-core/src/packageAuthoring.ts

Return whether an event bus exposes the acknowledged durable-publication capability.

function isAcknowledgedEventBus(bus: SlingshotEventBus): bus is AcknowledgedEventBus

Source: packages/slingshot-core/src/eventBus.ts

Detect whether a stored string looks like an encrypted ciphertext produced by encryptField.

Uses a lightweight structural check: a valid envelope has exactly 4 dot-separated parts (keyId.iv.ct.tag). Does not attempt decryption — use this to decide whether to call decryptField without the overhead of a full parse.

function isEncryptedField(value: string): boolean

Source: packages/slingshot-core/src/crypto.ts

Type guard that checks whether a value is a well-formed EventEnvelope.

Validates the structural shape: string key, object meta with string eventId, occurredAt, ownerPlugin, and an array exposure. When key is provided, also asserts that the envelope’s key matches.

function isEventEnvelope<K extends EventKey = EventKey>(value: unknown, key?: K,): value is EventEnvelope<K>

Source: packages/slingshot-core/src/eventEnvelope.ts

Recognize an HttpError regardless of which copy of this module created it. Prefer this over instanceof HttpError anywhere an error may cross a module boundary (framework error handlers, runtime adapters) — under Node, instanceof silently returns false for a genuine HttpError from a duplicate module instance, which would otherwise surface a 401/404 as a generic 500.

function isHttpError(err: unknown): err is HttpError

Source: packages/slingshot-core/src/errors.ts

Detect whether a definePackage(...)-authored package is registered on the active app context.

Works by checking for the framework-owned capabilities slot that publishPackageRuntimeState() writes for every registered package (always, even when the package publishes no capabilities of its own). Use this when a package needs to gate behavior on the presence of a sibling package without importing that sibling’s typed capability handle.

Returns false when the app context is missing or when the slot has not been published yet — i.e. during early setupMiddleware of the FIRST package, before any sibling has been bootstrapped.

function isPackageRegistered(app: object, packageName: string): boolean

Source: packages/slingshot-core/src/packageAuthoring.ts

Returns whether a plugin-state map has been sealed.

function isPluginStateSealed(pluginState: PluginStateMap): boolean

Source: packages/slingshot-core/src/pluginState.ts

Type guard used by the framework to detect a typed policy token at runtime.

function isPolicyToken(value: unknown): value is PolicyTokenRef

Source: packages/slingshot-core/src/entityRouteConfig.ts

Returns true if the IP is loopback, link-local, private, multicast, or otherwise unsafe for outbound requests to user-supplied URLs.

function isPrivateOrLoopbackIp(ip: string, family: 4 | 6): boolean

Source: packages/slingshot-core/src/http/safeFetch.ts

Returns whether a request path matches any declared public-path pattern.

Supported pattern forms:

  • exact path: /.well-known/assetlinks.json
  • prefix wildcard: /.well-known/*
function isPublicPath(path: string, publicPaths?: Iterable<string> | null): boolean

Source: packages/slingshot-core/src/publicPath.ts

Recognize a ValidationError across module boundaries — the duplicate-copy counterpart to isHttpError. Check this before isHttpError so the structured Zod issues payload is not lost (ValidationError is also an HttpError).

function isValidationError(err: unknown): err is ValidationError

Source: packages/slingshot-core/src/errors.ts

Returns true when room is a well-formed WebSocket room name.

Valid room names are 1–128 characters and may contain only alphanumeric characters, underscores (_), colons (:), dots (.), forward slashes (/), and hyphens (-). Entity channel rooms follow the convention {storageName}:{entityId}:{channelName}.

function isValidRoomName(room: string): boolean

Source: packages/slingshot-core/src/wsHelpers.ts

Internal: load all registered configs at app boot. Throws on the first validation failure with a structured per-field message.

function loadConfigs(configs: readonly ConfigDefinition<unknown>[], env: Readonly<Record<string, string | undefined>> = process.env as Readonly< Record<string, string | undefined> >,): void

Source: packages/slingshot-core/src/config.ts

Build a deterministic idempotency key by joining the supplied parts with :.

function makeIdempotencyKey(parts: ReadonlyArray<string | number>): IdempotencyKey

Source: packages/slingshot-core/src/idempotency/index.ts

Decide whether a subscription principal is entitled to an event given the envelope’s scope and exposures (tenant/user/app webhooks match by owner ID, connectors match by exposure, system principals never match).

function matchSubscriberToScope(principal: EventSubscriptionPrincipal, scope: EventScope | null, exposure: readonly EventExposure[],): boolean

Source: packages/slingshot-core/src/eventDefinition.ts

Auto-registers a module export as a named OpenAPI schema. Used internally by modelSchemas auto-discovery in createApp. Strips a trailing “Schema” suffix from the export name. Skips non-Zod values and already-registered schemas.

function maybeAutoRegister(exportName: string, value: unknown): void

Source: packages/slingshot-core/src/createRoute.ts

Read an entity adapter from plugin-owned state when available.

Returns null when the plugin has not published that entity adapter. Throws when the owning plugin’s state shape is malformed.

function maybeEntityAdapter<TAdapter extends object = object>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, lookup: EntityAdapterLookupInput<TAdapter>,): TAdapter | null

Source: packages/slingshot-core/src/pluginState.ts

Build a Zod schema for offset-based pagination query parameters (limit, offset).

Both params are strings (from query strings) — call parseOffsetParams() to convert them to numbers before passing to a repository.

function offsetParams(defaults?: OffsetParamDefaults): void

Source: packages/slingshot-core/src/pagination.ts

Internal pluginState key prefix under which package-provided capabilities are stored. Each providing package keeps its { [capabilityName]: resolvedValue } map under pluginState.get(${PACKAGE_CAPABILITIES_PREFIX}${pkg.name}). Out-of-request hook callers resolve capabilities by looking up the providing package via SlingshotContext.capabilityProviders and reading from this slot.

Exported as a stable internal contract so buildHookServices() and the framework package compiler stay aligned. Treat as framework-internal — consumer code should use ctx.capabilities.maybe() (request handlers) or services.capabilities.maybe() (out-of-request hooks) instead.

Source: packages/slingshot-core/src/packageAuthoring.ts

Build a Zod schema for a standard offset-paginated response envelope and register it in components/schemas under name.

The schema wraps an array of itemSchema with total, limit, and offset fields.

function paginatedResponse<T extends ZodType>(itemSchema: T, name: string): void

Source: packages/slingshot-core/src/pagination.ts

Server-truth projection of a content body into the entity’s sidecar fields.

Canonical normalization step every content-bearing entity (Thread, Reply, Message) should run after create/update so the stored mentions / broadcastMentions / mentionedRoleIds arrays reflect what was actually written in the body — not what a client claimed.

Bounded by MAX_CONTENT_MENTIONS to defend against pathological inputs.

Consumers (slingshot-community, slingshot-chat, app-side plugins) call this from a *.created bus subscriber and write the result back via a narrowly-scoped attachMentions field-update operation.

function parseBody(body: string | undefined | null, format: ContentFormat = 'markdown',): ParsedBody

Source: packages/slingshot-core/src/contentParser.ts

Parse content body into segments, extracting inline token references.

Walks the body once:

  1. Carve out code fences, then code spans — their contents are emitted as codeBlock / codeSpan segments and bypass all token scanning.
  2. For each remaining text run, scan left-to-right for the earliest token match (role mention → user mention → context ref → emoji). Backslash-escaped tokens (\<@id>) are passed through as literal text with the backslash stripped.
  3. Collect extracted reference IDs into the result arrays (deduped, insertion-ordered).

The parser is linear in body length and allocates O(segments) memory. Output objects are frozen before return.

function parseContentTokens(body: string): ParsedContent

Source: packages/slingshot-core/src/contentParser.ts

Parse and clamp raw cursor pagination query strings to safe values.

function parseCursorParams(raw: { limit?: string; cursor?: string }, defaults?: CursorParamDefaults,): ParsedCursorParams

Source: packages/slingshot-core/src/pagination.ts

Parse and clamp raw offset pagination query strings to safe numeric values.

Converts the string values produced by Hono’s query parsing into validated numbers, applying configured defaults when the client omits a parameter and clamping to the allowed range.

function parseOffsetParams(raw: { limit?: string; offset?: string }, defaults?: OffsetParamDefaults,): ParsedOffsetParams

Source: packages/slingshot-core/src/pagination.ts

The plugin name for slingshot-permissions. Used for plugin registration, dependency declarations, and event ownership.

Source: packages/slingshot-core/src/permissions.ts

Publish a capability implementation from a package during bootstrap finalization.

function provideCapability<TValue>(capability: PackageCapabilityHandle<TValue>, resolve: PublishedPackageCapability<TValue>['resolve'],): PublishedPackageCapability<TValue>

Source: packages/slingshot-core/src/packageAuthoring.ts

Publish canonical entity adapters into the owning plugin’s state.

The state entry is always a new frozen plain object. Existing top-level keys are preserved, and entityAdapters is replaced with a new frozen merged map. Re-publishing the same entity name with a different adapter instance is a startup error so dependent plugins never observe ambiguous adapter identity.

function publishEntityAdaptersState<TAdapter extends object>(pluginState: PluginStateMap, pluginName: string, entityAdapters: Record<string, TAdapter>,): Readonly<EntityAdaptersPluginState<TAdapter> & Record<string, unknown>>

Source: packages/slingshot-core/src/pluginState.ts

Publish plugin-owned state during framework bootstrap.

Accepts either a string key (legacy) or a typed PluginStateKey from definePluginStateKey. The typed form gives the value parameter compile-time type checking against the key’s value type.

function publishPluginState(pluginState: PluginStateMap, key: string, value: unknown): void; export function publishPluginState<T>( pluginState: PluginStateMap, key: PluginStateKey<T>, value: T, ): void; export function publishPluginState( pluginState: PluginStateMap, key: string | PluginStateKey<unknown>, value: unknown, ): void

Source: packages/slingshot-core/src/pluginState.ts

Read a typed plugin-state slot.

Returns undefined when the slot is absent. The return type is inferred from the typed key, replacing the pluginState.get(KEY) as Foo | undefined pattern with a compile-time checked lookup.

function readPluginState<T>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, key: PluginStateKey<T>,): T | undefined

Source: packages/slingshot-core/src/pluginState.ts

Framework-internal registration hook for rebuilding an entity adapter against a transaction-bound infrastructure view.

Source: packages/slingshot-core/src/storeInfra.ts

Register plugin-tier capability providers so consumers can resolve them through the standard ctx.capabilities.require(...) / services.capabilities.require(...) APIs.

Packages declared with definePackage(...) register their capabilities automatically through compilePackages(...). Plugins are framework-tier and don’t go through that pipeline, so they call this helper from setupPost to publish their capabilities.

Every published handle’s contract (when set) must equal pluginName — that’s the same ownership rule the package-tier path enforces. Duplicate providers across packages or plugins throw with a clear conflict message.

async function registerPluginCapabilities(ctx: { readonly capabilityProviders?: ReadonlyMap<string, string>; readonly pluginState: PluginStateMap; }, pluginName: string, provided: ReadonlyArray<PublishedPackageCapability<unknown>>,): Promise<void>

Source: packages/slingshot-core/src/packageAuthoring.ts

Registers a Zod schema as a named entry in components/schemas.

Use this for shared schemas (e.g. shared error types, reusable response shapes) that aren’t directly attached to a specific route. Schemas already registered under the same name are silently skipped.

function registerSchema<T extends ZodType>(name: string, schema: T): T

Source: packages/slingshot-core/src/createRoute.ts

Registers multiple Zod schemas at once as named entries in components/schemas. Object keys become the schema names. Returns the same object so you can destructure or re-export the schemas normally.

Schemas already registered (e.g. via a prior registerSchema call) are skipped.

Source: packages/slingshot-core/src/createRoute.ts

The relation builder namespace — creates informational RelationDef values for use in EntityConfig.relations.

Relations are metadata only — they inform code generators and admin tools but do NOT cause automatic joins in adapters.

Source: packages/slingshot-core/src/entityConfig.ts

Read an entity adapter from plugin-owned state.

Throws with a startup-focused error when the provider plugin has not published the requested adapter yet.

function requireEntityAdapter<TAdapter extends object = object>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, lookup: EntityAdapterLookupInput<TAdapter>,): TAdapter

Source: packages/slingshot-core/src/pluginState.ts

Read a typed plugin-state slot, throwing when absent.

Use this when the slot is guaranteed to be present at the read site (e.g., the consumer declares the provider plugin as a dependency). Throws a startup-focused error otherwise.

function requirePluginState<T>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, key: PluginStateKey<T>,): T

Source: packages/slingshot-core/src/pluginState.ts

Reflect symbol injected by the framework bootstrap onto StoreInfra.

The injected value is createCompositeFactories from the framework’s config-driven persistence layer. Use Reflect.get(infra, RESOLVE_COMPOSITE_FACTORIES) inside a composite buildAdapter closure to create RepoFactories<T> for a multi-entity composite without a direct import from the root app.

See CLAUDE.md Rule 16.

Source: packages/slingshot-core/src/storeInfra.ts

Reflect symbol injected by the framework bootstrap onto StoreInfra.

The injected value is createEntityFactories from the framework’s config-driven persistence layer. Use Reflect.get(infra, RESOLVE_ENTITY_FACTORIES) inside a buildAdapter closure to create RepoFactories<T> from an entity config without a direct import from the root app.

This is the DI mechanism that lets buildAdapter closures inside a package’s entity-module wiring create factories without a direct import from the root app. See CLAUDE.md Rule 16.

Source: packages/slingshot-core/src/storeInfra.ts

Reflect symbol injected onto StoreInfra by the entity plugin during setupPost.

The injected value is (entityStorageName: string) => AsyncIterable<Record<string, unknown>> | null.

Used by the search admin rebuild route to obtain a full data scan for a given entity without a direct import from the entity plugin. Returns null when no scan source is registered for the entity (entity plugin absent, or entity has no search config).

See CLAUDE.md Rule 16.

Source: packages/slingshot-core/src/storeInfra.ts

Framework-internal resolver used by package and hook entity readers when a transaction scope is supplied.

Source: packages/slingshot-core/src/storeInfra.ts

Resolve the canonical Actor from a HandlerMeta object.

function resolveActor(meta: HandlerMeta): Actor

Source: packages/slingshot-core/src/handler.ts

Resolve a typed package capability from outside the request scope.

Plugins use this from setupPost (or other lifecycle phases) to consume capabilities published by other plugins/packages — when the consumer doesn’t have a Hono context but does have the SlingshotContext + pluginState. Returns undefined when the capability isn’t provided. Mirrors the resolution ctx.capabilities.maybe(...) performs at request time, but works in plugin lifecycle code.

function resolveCapabilityValue<TValue>(ctx: { readonly capabilityProviders?: ReadonlyMap<string, string>; readonly pluginState: PluginStateMap; }, capability: PackageCapabilityHandle<TValue>,): TValue | undefined

Source: packages/slingshot-core/src/packageAuthoring.ts

Resolve a SlingshotContext from a ContextCarrier.

If input is already a branded SlingshotContext, it is returned as-is. Otherwise, getContext(input) is called to retrieve the context attached to the app instance.

Remarks: Explicit branding: SlingshotContext is an interface (no instanceof check is possible), so contexts are identified via an internal non-enumerable symbol brand that attachContext() installs on the real context object. This avoids false positives from arbitrary objects that resemble the context shape but were never created by framework bootstrap.

Remarks: This is an internal helper used by all context-accessor exports in slingshot-core. Plugin code should use the typed accessor helpers (getRequestActorResolver, etc.) instead of calling resolveContext directly.

function resolveContext(input: ContextCarrier): SlingshotContext

Source: packages/slingshot-core/src/context/contextAccess.ts

Resolve a match record against runtime params.

Expands 'param:x' references using the params map and returns a plain { field: resolvedValue } record. Literal values are passed through unchanged.

function resolveMatch(match: Record<string, string | number | boolean>, params: Record<string, unknown>,): Record<string, unknown>

Source: packages/slingshot-core/src/filterEvaluator.ts

Merge operation-level defaults with the specific config for a named operation.

Precedence: specific CRUD field (e.g. routeConfig.create) or named operation (e.g. routeConfig.operations.publish) > routeConfig.defaults.

function resolveOpConfig(routeConfig: EntityRouteConfig, opName: string,): RouteOperationConfig | undefined

Source: packages/slingshot-core/src/entityRouteConfig.ts

Extract a PluginStateMap from a raw map, a carrier object, or null.

Returns null when the input is null, undefined, or not a recognised plugin-state container. Does not fall back to the ambient context.

function resolvePluginState(input: PluginStateMap | PluginStateCarrier | null | undefined,): PluginStateMap | null

Source: packages/slingshot-core/src/pluginState.ts

Resolve a repository instance from a RepoFactories map for the configured store type.

Dispatches to the correct factory based on storeType, passing infra as the dependency bundle. Throws if the store type is not present in the factory map.

function resolveRepo<T>(factories: RepoFactories<T>, storeType: StoreType, infra: StoreInfra,): T

Source: packages/slingshot-core/src/storeInfra.ts

Like resolveRepo but supports factories that return a Promise.

Use this when the selected adapter requires async initialization (e.g., running database migrations or establishing a persistent connection on first use).

async function resolveRepoAsync<T>(factories: Record<StoreType, (infra: StoreInfra) => T | Promise<T>>, storeType: StoreType, infra: StoreInfra,): Promise<T>

Source: packages/slingshot-core/src/storeInfra.ts

Entrypoint for declaring package domain routes, with withServices() to bind a typed service bag for handler IntelliSense.

Source: packages/slingshot-core/src/packageAuthoring.ts

Construct a typed RouteKey from an HTTP method and path.

Use this to define ROUTES constants in plugin packages. shouldMountRoute calls the same function internally, ensuring the constant value and the runtime check always match.

function routeKey<M extends string, P extends string>(method: M, path: P): RouteKey<M, P>

Source: packages/slingshot-core/src/routeOverrides.ts

Per-subsystem SQLite migration runner.

Tracks applied migrations in a shared _slingshot_migrations table keyed by subsystem name, rather than the global PRAGMA user_version. This allows multiple subsystems (auth, permissions, webhooks, push) to share the same SQLite file without colliding on the single global version integer.

The _slingshot_migrations table is created automatically if it doesn’t exist. Each row records the highest migration index applied for a given subsystem. Migration execution is serialized with BEGIN IMMEDIATE so concurrent processes cannot both read the same stale version and race each other through the same schema change.

function runSubsystemMigrations(db: RuntimeSqliteDatabase, subsystem: string, migrations: ReadonlyArray<(db: RuntimeSqliteDatabase) => void>,): void

Source: packages/slingshot-core/src/sqliteMigrations.ts

Safely join a user-supplied relative path under a fixed base directory.

path.resolve alone is INSUFFICIENT — path.resolve('/safe', '../etc/passwd') returns /etc/passwd, which escapes the base. This helper performs the resolve and then verifies the result lies under baseDir + path.sep (or equals baseDir exactly), throwing PathTraversalError otherwise.

Rejects:

  • Non-string inputs.
  • Inputs containing a NUL byte (\0) — some Node APIs misbehave on these.
  • Any resolved path outside baseDir.

Use this whenever an externally-supplied value (URL pathname, manifest route name, upload key, config field) is concatenated with a directory before being handed to fs.* or any other filesystem operation.

function safeJoin(baseDir: string, userPath: string): string

Source: packages/slingshot-core/src/lib/safePath.ts

Reject any string containing \r, \n, or NUL — the byte sequences that terminate an HTTP / email / queue header line and let an attacker craft additional headers (“response splitting” / header injection).

Returns the input unchanged when it is safe so legitimate callers see no behavior change. Throws HeaderInjectionError otherwise. The surrounding code is expected to surface the error as a 4xx / config rejection so the caller learns immediately rather than silently producing a stripped value that may mask other validation bugs.

function sanitizeHeaderValue(value: string, header?: string): string

Source: packages/slingshot-core/src/lib/sanitize.ts

Escape \r, \n, and NUL in a value destined for a log line so the record cannot be split or smuggled by user-controlled bytes.

Unlike sanitizeHeaderValue, this never throws — logging must always succeed even when the input is malicious. Non-string inputs are coerced via String() so callers can pass identifiers and error messages without pre-stringifying.

The escape representation matches the JSON-like convention (\\r, \\n, \\0) so downstream log readers can recognise and unescape the value if they need to display it verbatim.

function sanitizeLogValue(value: unknown): string

Source: packages/slingshot-core/src/lib/sanitize.ts

Seal plugin state after app bootstrap so late mutations fail loudly.

function sealPluginState(pluginState: PluginStateMap): void

Source: packages/slingshot-core/src/pluginState.ts

Complete list of all security.* event keys defined in SlingshotEventMap.

Used by the audit log plugin to identify events that must never reach browser clients. The array is frozen and typed as ReadonlyArray<SecurityEventKey>.

Source: packages/slingshot-core/src/eventBus.ts

Internal: install the per-request store. Used by the framework middleware.

function setRequestScopeStore(c: Context, store: RequestScopeStore): void

Source: packages/slingshot-core/src/requestScope.ts

Attach a resolved socket IP address to a raw Request object for standalone upgrade/auth flows that do not have a Hono Context.

This is used by WS/SSE upgrade handlers so downstream auth helpers can enforce IP-based session binding with the same semantics as normal HTTP requests.

function setStandaloneClientIp(req: Request, value: string): void

Source: packages/slingshot-core/src/clientIp.ts

Attach a trust-proxy depth to a raw Request object for standalone (non-framework) usage.

When using getClientIp outside of a full Slingshot app (e.g., in a plain Hono server), call this function before the request reaches the handler so getClientIp can read the correct proxy trust depth from the request.

Remarks: Side effects: this function mutates the Request object by defining a non-enumerable property keyed by an internal Symbol. The mutation is confined to the single Request instance — it does not affect other requests or global state. The property is configurable: true so it can be overwritten by a subsequent call with a different value on the same request object.

Remarks: In a full Slingshot app, do NOT call this — set trustProxy in the app config instead and the framework reads it from SlingshotContext. This function is only for plain Hono servers that call getClientIp() directly without a SlingshotContext in scope.

function setStandaloneTrustProxy(req: Request, value: false | number): void

Source: packages/slingshot-core/src/clientIp.ts

SHA-256 hash a string and return the lowercase hex digest.

Centralised to avoid duplicate implementations across modules. Uses Node’s built-in crypto.createHash — synchronous and available in all environments.

function sha256(input: string): string

Source: packages/slingshot-core/src/crypto.ts

Returns true if the route should be mounted — i.e., it is NOT in disabledRoutes.

Constructs a RouteKey from method and path internally, so the check is always consistent with constants defined using routeKey().

function shouldMountRoute(method: string, path: string, disabledRoutes?: readonly string[],): boolean

Source: packages/slingshot-core/src/routeOverrides.ts

Strip content tokens from body text for search indexing.

Removes <@userId>, <#contextId>, and :shortcode: tokens so that search queries don’t match token syntax. Collapses resulting whitespace.

function stripContentTokens(body: string): string

Source: packages/slingshot-core/src/contentParser.ts

The magic role name that bypasses all permission checks.

Any subject with this role in their effective grants is allowed to perform any action on any resource without the evaluator consulting the registry. Grant this role with extreme caution.

Source: packages/slingshot-core/src/permissions.ts

Create an AbortSignal that aborts after timeoutMs. The returned signal is independent — callers do not need to dispose of anything when the operation completes early.

function timeoutSignal(timeoutMs: number): AbortSignal

Source: packages/slingshot-core/src/concurrency/withTimeout.ts

Constant-time string comparison to prevent timing attacks on secret verification.

Uses Node.js’s native crypto.timingSafeEqual so that the comparison time is independent of how many characters match. When the strings differ in length, a same-buffer compare is performed to burn equivalent time before returning false.

function timingSafeEqual(a: string, b: string): boolean

Source: packages/slingshot-core/src/crypto.ts

Convert an OpenAPI-style path (/posts/{id}) into the hono form (/posts/:id) that the live router matches against.

createRoute(...) accepts brace paths and converts them internally, but bare router.use(path, mw) does NOT — hono matches {id} as a literal segment, so middleware registered with a brace path silently never runs for real requests. Any path handed directly to the router (middleware registration) must go through this first. Idempotent on paths that already use the colon form.

function toHonoPath(path: string): string

Source: packages/slingshot-core/src/mount.ts

Convert a hono-style path (/posts/:id, /users/:id?, /posts/:slug{.+}) into the OpenAPI form (/posts/{id}, /users/{id}, /posts/{slug}).

Hono uses colon-prefixed parameters; OpenAPI emits and codegen tools (including the Slingshot snapshot client) expect {name} braces. The framework’s runtime router still needs the colon form, so this conversion only applies at the boundary where a path is handed to createRoute(...) / the OpenAPI registry — never to the live router.

Idempotent on already-converted {name} segments. Strips hono’s optional marker (:id?) and regex constraint (:slug{.+}) since OpenAPI represents them as plain {slug} without those modifiers.

function toOpenApiPath(path: string): string

Source: packages/slingshot-core/src/mount.ts

Validate that an adapter object implements all required method signatures.

Checks that each name in requiredMethods exists on adapter and is a function. Throws a single Error listing all absent or non-function properties if any are missing.

Remarks: TypeScript interface types are erased at runtime. An adapter supplied as a plain config value (e.g., a user-constructed object literal) may satisfy the TypeScript type while missing methods at runtime — for example when transpiling with isolatedModules or when the adapter arrives from a dynamic require(). This function enforces the contract explicitly at server startup so failures are caught early with a clear message rather than producing a cryptic TypeError: x is not a function inside a request handler.

function validateAdapterShape(pluginName: string, adapterLabel: string, adapter: unknown, requiredMethods: string[],): void

Source: packages/slingshot-core/src/configValidation.ts

Validate an entity channel config object against entityChannelConfigSchema.

Returns { success: true } on valid input, or { success: false, errors } with structured Zod validation errors on failure. Never throws — all error information is returned in the result object so callers can surface messages without try/catch.

Call this during plugin bootstrap or server startup to catch misconfigured channel declarations before any WebSocket routes are registered.

Remarks: This function does not throw. If you need the validated, typed value rather than a boolean result, use entityChannelConfigSchema.parse(config) directly (which does throw).

function validateEntityChannelConfig(config: unknown): void

Source: packages/slingshot-core/src/entityChannelConfigSchema.ts

Validate an entity route config object against entityRouteConfigSchema.

Returns { success: true } on valid input, or { success: false, errors } with structured Zod validation errors on failure. Never throws — all error information is returned in the result object so callers can surface messages without try/catch.

Call this during plugin bootstrap or server startup to catch misconfigured entity route declarations (invalid auth strategies, forbidden event namespaces, malformed duration strings, etc.) before any routes are registered.

Remarks: This function does not throw. If you need the validated, typed value rather than a boolean result, use entityRouteConfigSchema.parse(config) directly (which does throw).

function validateEntityRouteConfig(config: unknown): void

Source: packages/slingshot-core/src/entityRouteConfigSchema.ts

Validate an event definition, throwing if ownerPlugin is empty, no exposure is declared, exposures are duplicated, or internal is mixed with external exposures.

function validateEventDefinition<K extends EventKey>(definition: EventDefinition<K>): void

Source: packages/slingshot-core/src/eventDefinition.ts

Validate a payload against the registry and apply the selected validation mode. Returns Zod-transformed data on success.

function validateEventPayload(event: string, payload: unknown, registry: EventSchemaRegistry | undefined, mode: ValidationMode, logger?: Logger,): unknown

Source: packages/slingshot-core/src/eventSchemaRegistry.ts

Validate a permission grant before it is persisted.

Enforces the following rules:

  • resourceId requires resourceType to be non-null
  • At least one role must be specified
  • effect must be 'allow' or 'deny'
  • expiresAt, when provided, must be a Date in the future
  • subjectType must be one of 'user' | 'group' | 'service-account'
function validateGrant(grant: Omit<PermissionGrant, 'id' | 'grantedAt'>): void

Source: packages/slingshot-core/src/permissions.ts

Validate a plugin config object using its Zod schema.

Parses rawConfig with schema.safeParse. On success, warns about unknown keys via warnUnknownPluginKeys and returns the strongly-typed parsed config. On failure, throws a formatted Error listing all Zod validation issues.

The return type is derived directly from schema — no explicit type parameter is needed at the call site.

Remarks: try-catch / recovery behaviour: safeParse is used instead of parse so that all validation issues can be collected and reported together in one error, rather than halting on the first issue. There is no recovery from a validation failure — the error is rethrown immediately and server startup aborts. Unknown keys are only warned about (not thrown) so that future schema additions remain backwards-compatible.

Remarks: Unknown-key detection runs only when rawConfig is a non-null, non-array object. Primitive or array configs pass through without unknown-key warnings.

function validatePluginConfig<S extends z.ZodType>(pluginName: string, rawConfig: unknown, schema: S, logger?: Logger,): z.infer<S>

Source: packages/slingshot-core/src/configValidation.ts

Wrap an async operation with idempotency-aware execution.

On a cache hit (and when reuseCachedPayload is true, the default), this returns the prior payload with deduped: true and does not invoke fn. Otherwise it invokes fn, records the result under key, and returns it.

async function withIdempotency<T>(adapter: IdempotencyAdapter, key: IdempotencyKey, fn: () => Promise<T>, opts?: WithIdempotencyOptions,): Promise<

Source: packages/slingshot-core/src/idempotency/index.ts

Adds an OpenAPI security requirement to a route without affecting TypeScript type inference on the handler. Pass each security scheme as a separate object.

Use this instead of inlining security in createRoute(...) — inlining a field typed as { [name: string]: string[] } breaks c.req.valid() inference.

function withSecurity<T extends RouteConfig>(route: T, ...schemes: Array<Record<string, string[]>>): T

Source: packages/slingshot-core/src/createRoute.ts

Restore identity for exactly one callback without module-global mutation.

async function withTenantExecutionContext<T>(snapshot: TenantExecutionContextSnapshot, callback: (context: TenantExecutionContextSnapshot) => T | Promise<T>,): Promise<T>

Source: packages/slingshot-core/src/context/tenantExecutionContext.ts

Wrap a promise with an upper-bound timeout. Resolves or rejects with the underlying promise’s outcome if it settles before timeoutMs. Otherwise rejects with a TimeoutError. The internal timer is cleared as soon as the underlying promise settles, so this helper does not leak timers.

function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label?: string): Promise<T>

Source: packages/slingshot-core/src/concurrency/withTimeout.ts

Frozen anonymous actor singleton.

Source: packages/slingshot-core/src/identity.ts

Zod schema for validating an AssetRef in request bodies.

Source: packages/slingshot-core/src/content.schemas.ts

Stable plugin-state key published by slingshot-chat. Used by the interactions peer bridge (probeChatPeer) to discover chat’s published interactionsPeer.

Source: packages/slingshot-core/src/pluginKeys.ts

Stable plugin-state key published by slingshot-community. Used by the interactions peer bridge (probeCommunityPeer) to discover community’s published interactionsPeer.

Source: packages/slingshot-core/src/pluginKeys.ts

Zod schema for contact data.

Source: packages/slingshot-core/src/content.schemas.ts

Cookie name for the CSRF synchronizer token. Set as a readable (non-HttpOnly) cookie so that JavaScript can copy it into the header.

Source: packages/slingshot-core/src/constants.ts

Cookie name for the long-lived refresh token (HttpOnly, secure). Used by the auth plugin to issue new access tokens without re-authentication.

Source: packages/slingshot-core/src/constants.ts

Cookie name for the session access token (HttpOnly, short-lived). Used by the auth plugin to set and read the primary session credential.

Source: packages/slingshot-core/src/constants.ts

Default maximum entry count for development and test in-memory stores.

Applied by createMemoryRateLimitAdapter and createMemoryCacheAdapter to prevent unbounded growth in long-running dev processes.

Source: packages/slingshot-core/src/memoryEviction.ts

Stable plugin-state key published by slingshot-embeds.

Source: packages/slingshot-core/src/pluginKeys.ts

HTTP request header name for the CSRF token submitted by the client. The CSRF middleware compares this value against COOKIE_CSRF_TOKEN.

Source: packages/slingshot-core/src/constants.ts

HTTP header name for the client-provided idempotency key. Used by the idempotency middleware to deduplicate mutating requests.

Source: packages/slingshot-core/src/constants.ts

HTTP header name for the refresh token (alternative to cookie transport).

Source: packages/slingshot-core/src/constants.ts

HTTP header name for the per-request trace identifier. Set by the request-id middleware and echoed in all error responses.

Source: packages/slingshot-core/src/constants.ts

HTTP header name for the HMAC request signature. Used by the webhook signing middleware to verify inbound webhook authenticity.

Source: packages/slingshot-core/src/constants.ts

HTTP header name for the request timestamp included in the HMAC signature. The signing middleware rejects requests with a timestamp outside the replay window.

Source: packages/slingshot-core/src/constants.ts

HTTP header name for the session access token (alternative to cookie transport). Used by SPA and mobile clients that manage tokens in memory.

Source: packages/slingshot-core/src/constants.ts

Singleton JSON serializer instance. Stateless and safe to share.

Source: packages/slingshot-core/src/eventSerializer.ts

Zod schema for location data.

Source: packages/slingshot-core/src/content.schemas.ts

Hard cap on the number of attachments in a single content entity.

Source: packages/slingshot-core/src/content.ts

Hard cap on a content entity’s body field. Schema layer enforces this.

Source: packages/slingshot-core/src/content.ts

Hard cap on the number of mentions in a single content entity.

Source: packages/slingshot-core/src/content.ts

Logger that drops every record. Safe default for tests and benchmarks.

Source: packages/slingshot-core/src/observability/logger.ts

Generated package stability metadata. Do not edit by hand.

Source: packages/slingshot-core/src/generated/packageMaturity.ts

Zod schema for validating a QuotePreview.

Source: packages/slingshot-core/src/content.schemas.ts

Stable plugin-state key published by slingshot-search.

Source: packages/slingshot-core/src/searchPluginRuntime.ts

Zod schema for system event data.

Source: packages/slingshot-core/src/content.schemas.ts

Raised when an entity changed after the caller read its expected version.

Source: packages/slingshot-core/src/entityConcurrency.ts

Raised when a concurrency-enabled write requires an expected version but none was supplied.

Source: packages/slingshot-core/src/entityConcurrency.ts

HTTP 409 error for a guarded or required transaction mutation that did not apply.

Source: packages/slingshot-core/src/transactions.ts

Structured transport-agnostic handler failure.

Throw a HandlerError from guards or handlers to signal a well-defined failure with an HTTP-style status code, optional machine-readable error code, and arbitrary detail payload. The framework serialises these into the appropriate transport response.

Source: packages/slingshot-core/src/handler.ts

Thrown by sanitizeHeaderValue when a header value contains a control character that would let a caller inject additional header lines.

The error intentionally does not embed the offending value to avoid leaking attacker-controlled bytes into error logs or telemetry.

Source: packages/slingshot-core/src/lib/sanitize.ts

HTTP-aware error carrying a response status and optional machine-readable code.

Source: packages/slingshot-core/src/errors.ts

Sentinel used by the idempotency guard to short-circuit execution.

When a guard detects that a request carries an HandlerMeta.idempotencyKey that has already been processed, it throws an IdempotencyCacheHit carrying the previously computed output. The handler pipeline catches this sentinel, validates the cached output against the output schema, and returns it without re-running the handler or after hooks.

Source: packages/slingshot-core/src/handler.ts

In-process SlingshotEventBus implementation.

All listeners run in the same process, in the same event loop. Async listeners are fire-and-forget from the emitter’s perspective — errors are caught and logged. Use drain() in tests to wait for all in-flight async handlers to settle.

Remarks: InProcessAdapter does not support durable subscriptions. Durable subscription requests degrade to non-durable with a console warning.

Remarks: For production multi-instance deployments, swap this for a queue-backed adapter (e.g., Redis Streams).

Source: packages/slingshot-core/src/eventBus.ts

Default JSON serializer. Matches the existing behavior in BullMQ and Kafka adapters — JSON.stringify on produce, JSON.parse on consume.

Source: packages/slingshot-core/src/eventSerializer.ts

Thrown when a path operation would escape its configured base directory.

Used by safeJoin to surface path-traversal attempts (.. segments, absolute paths, null bytes, or any input that resolves outside the allowed root). Callers should treat this as a 4xx-class input error rather than an internal failure: the input was untrusted and rejected.

Source: packages/slingshot-core/src/lib/safePath.ts

Thrown when the resolved IP for a target hostname fails the allow-policy.

Source: packages/slingshot-core/src/http/safeFetch.ts

Thrown when DNS resolution for a target hostname fails or returns no records.

Source: packages/slingshot-core/src/http/safeFetch.ts

Base error class for all Slingshot errors.

Carries a machine-readable code string for programmatic discrimination and an optional cause for error chaining. Feature packages should extend this class (or one of the HTTP-aware subclasses) rather than throwing generic Error instances.

Source: packages/slingshot-core/src/errors.ts

Thrown by MailRenderer.render() when the requested template name does not exist in the renderer’s template store.

Source: packages/slingshot-core/src/mail.ts

Thrown by withTimeout when the configured timeout elapses before the wrapped promise settles.

Source: packages/slingshot-core/src/concurrency/withTimeout.ts

HTTP 400 error for a missing or malformed declarative transaction binding.

Source: packages/slingshot-core/src/transactions.ts

Thrown when commit fails, including whether rollback can be proven.

Source: packages/slingshot-core/src/transactions.ts

Reports framework-owned post-commit failures without claiming the database rolled back.

Source: packages/slingshot-core/src/transactions.ts

Thrown when a retained scope or scoped adapter is used after its callback settles.

Source: packages/slingshot-core/src/transactions.ts

Thrown for a forged scope, a foreign-app scope, or a scope owned by another manager.

Source: packages/slingshot-core/src/transactions.ts

Thrown when nested or entity work targets a store different from the active scope.

Source: packages/slingshot-core/src/transactions.ts

Thrown when an app cannot provide a real transaction for the requested store.

Source: packages/slingshot-core/src/transactions.ts

Thrown after rollback when a callback returned with scope-bound work still pending.

Source: packages/slingshot-core/src/transactions.ts

Thrown when a method is called on an adapter that does not support the requested feature.

Use this when implementing optional adapter capabilities that a caller may invoke conditionally. Throwing this error surfaces a clear, actionable message instead of a silent no-op or opaque crash.

Source: packages/slingshot-core/src/errors.ts

HTTP 400 error that preserves structured Zod validation issues.

Source: packages/slingshot-core/src/errors.ts

Optional event-bus capability used by the transactional outbox dispatcher.

This is intentionally separate from fire-and-forget SlingshotEventBus.emit.

Source: packages/slingshot-core/src/eventBus.ts

Canonical identity for the current request.

All framework consumers (guards, permissions, data scoping, audit, entity routes) read identity through this shape rather than reaching into raw Hono context variables or HandlerMeta legacy fields.

Source: packages/slingshot-core/src/identity.ts

A pluggable admin authentication provider.

Verifies incoming requests to the admin API and returns an AdminPrincipal. Implement this interface to integrate any identity provider (JWT, OIDC, API key, etc.) as an admin access mechanism.

Source: packages/slingshot-core/src/adminProvider.ts

The authenticated admin identity extracted from a verified admin request. Produced by AdminAccessProvider.verifyRequest() and carried through admin routes.

Source: packages/slingshot-core/src/adminProvider.ts

Arguments passed to the afterInvoke hook, extending BeforeInvokeArgs with the handler’s output, error, and latency.

Source: packages/slingshot-core/src/functions.ts

Aggregate operation — compute summary statistics over a set of records.

Optionally groups results by a field value. Each key in compute produces a calculated column (count, sum, avg, min, max).

Source: packages/slingshot-core/src/operations.ts

Remove all occurrences of a value from an array field on a record identified by its primary key.

Uses the same value binding syntax as ArrayPushOpConfig.

Route: DELETE /{entity}/:id/{op-kebab}

Source: packages/slingshot-core/src/operations.ts

Append a value to an array field on a record identified by its primary key.

When dedupe is true (the default), the value is only appended if it is not already present — making the operation idempotent.

The value binding is resolved at the HTTP layer before the executor is called. Supported binding syntax:

  • 'ctx:key' → read from Hono context (e.g. 'ctx:actor.id')
  • 'param:key' → read from URL path param
  • 'input:key' → read from JSON request body field
  • literal → constant value baked in

Route: POST /{entity}/:id/{op-kebab}

Source: packages/slingshot-core/src/operations.ts

Replace the entire contents of an array field on a record identified by its primary key.

Unlike arrayPush and arrayPull, which mutate individual values, arraySet performs a full replacement — the stored array becomes exactly value (after optional server-side deduplication).

The value binding is resolved at the HTTP layer before the executor is called. Supported binding syntax:

  • 'input:key' → read an array from the JSON request body field key
  • 'param:key' → read from a URL path param (parsed as JSON if it’s an array string)
  • 'ctx:key' → read from Hono context
  • literal → constant array baked in (rare)

Route: PUT /{entity}/:id/{op-kebab} (full-replacement semantics)

Source: packages/slingshot-core/src/operations.ts

Reference to an uploaded asset. Stored in the attachments field of content entities. The assetId references an Asset record from slingshot-assets.

Clients use the asset ID to fetch a presigned download URL via the assets plugin.

Source: packages/slingshot-core/src/content.ts

A single audit log entry recording an HTTP request or admin action.

Stored by AuditLogProvider.logEntry() and queryable via AuditLogProvider.getLogs(). The audit middleware creates entries automatically for authenticated requests.

Source: packages/slingshot-core/src/auditLog.ts

Storage and query contract for the audit log.

Implemented by backing store adapters (memory, SQLite, Mongo, Postgres). Registered via ResolvedPersistence.auditLog and called by the audit middleware.

Source: packages/slingshot-core/src/auditLog.ts

Filters for querying the audit log. All fields are optional and combined with AND semantics.

Remarks: Multiple filter fields are ANDed together — only entries matching ALL specified filters are returned. There is no OR or NOT support at the query level. To query across disjoint criteria (e.g., entries for user A OR user B), issue two separate queries and merge the results in application code.

Remarks: Tenant isolation contract — when requestTenantId is supplied (a non-undefined value, including null), implementations MUST treat it as a HARD security filter: only entries whose stored requestTenantId exactly equals the supplied value may be returned. Treating requestTenantId as a hint, ignoring it, or using fuzzy matching constitutes a tenant-isolation violation. Callers are responsible for passing the authenticated principal’s tenant on every query that should be tenant-scoped — the adapter does NOT infer tenancy on its own. Pass undefined (omit the field) only when the caller has already verified that a cross-tenant read is authorized.

Source: packages/slingshot-core/src/auditLog.ts

Minimal peer-facing auth runtime shape shared through ctx.pluginState.

This intentionally models only the cross-package surface needed by packages that coordinate with auth without importing @lastshotlabs/slingshot-auth.

Source: packages/slingshot-core/src/authPeer.ts

Normalized result returned by auth-controlled account access decisions.

Source: packages/slingshot-core/src/authPeer.ts

Request metadata passed into auth-controlled account access decisions.

Source: packages/slingshot-core/src/authPeer.ts

Batch operation — update or delete multiple records matching a filter in one call.

Returns the number of affected rows. Optionally atomic (transaction-wrapped) when the backend supports a real transaction and the caller wants the stricter boundary.

Source: packages/slingshot-core/src/operations.ts

Arguments passed to the beforeInvoke hook with the decoded input, handler meta, trigger name, cold-start flag, and context.

Source: packages/slingshot-core/src/functions.ts

CAPTCHA middleware configuration for protecting public auth endpoints.

When configured, the CAPTCHA middleware validates a client-submitted token before allowing registration, login, or password-reset requests to proceed.

Source: packages/slingshot-core/src/captcha.ts

Bus events to forward to subscribers of a WebSocket channel.

When one of the listed bus events fires, the framework extracts the entity ID from the event payload using idField (defaulting to the entity’s primary key field name) and delivers the payload to all clients subscribed to the matching room {storageName}:{entityId}:{channelName}.

Remarks: Only events whose registry definitions allow external delivery are eligible to be forwarded to WebSocket subscribers. Attempting to forward an event without client-safe exposure is a configuration error caught at startup. List at least one event in events; the schema enforces a minimum length of 1.

Source: packages/slingshot-core/src/entityChannelConfig.ts

A single named incoming WebSocket event handler declaration.

Returned by buildReceiveIncoming() and merged into WsEndpointConfig.incoming. The framework’s wsDispatch.handleIncomingEvent() dispatches { action: 'event', type } messages to the matching handler.

Remarks: The handler signature matches WsEventHandler from src/config/types/ws.ts. The ws parameter is opaque (unknown) at the slingshot-core boundary — framework code casts it to ServerWebSocket<SocketData> at use sites.

Source: packages/slingshot-core/src/entityChannelConfig.ts

Permission check applied when a client subscribes to a WebSocket channel. Mirrors RoutePermissionConfig from entityRouteConfig.ts but for the WS subscription layer. The framework evaluates the permission grant before accepting the subscription — clients that fail the check are rejected immediately.

Remarks: ownerField enables entity-ownership checks: the framework reads the value of the named entity field and compares it to the authenticated subscriber’s user ID. Set or to allow an alternative action (e.g., an admin override) to satisfy the permission in addition to requires.

Source: packages/slingshot-core/src/entityChannelConfig.ts

Whitelisted client-sent events that the server will relay to channel subscribers.

When a client sends { action: 'event', type: 'document.typing', payload: { room: '...' } }, the framework validates that the event type is in the channel’s receive.events whitelist, that the sender is subscribed to the declared room, and then broadcasts the payload to all other subscribers of that room.

Use receive for lightweight ephemeral signals (typing indicators, cursor positions) that must be relayed in real time without server-side processing.

Remarks: The channel’s auth config is not re-checked at receive time — auth is enforced at subscribe time only. However, room membership (the sender must be subscribed to the room) is always checked before relay. Clients that send events for rooms they are not subscribed to are silently dropped.

Remarks: The event type whitelist (events) applies at the channel level, not the endpoint level. Declare each event type in exactly one channel’s receive.events — duplicates across channels result in only one handler being registered (last-wins in the buildReceiveIncoming merge).

Source: packages/slingshot-core/src/entityChannelConfig.ts

Collection operation — manage an embedded ordered list of sub-documents within a parent entity.

Provides typed list/add/remove/update/set methods for arrays stored as a JSON field (Postgres/SQLite) or embedded array (Mongo).

Source: packages/slingshot-core/src/operations.ts

Computed aggregate operation — query one entity, aggregate it, and materialise the result back into another entity (the “target”).

Used for denormalised summary fields (e.g., commentCount on a Post).

Source: packages/slingshot-core/src/operations.ts

A field-level computed aggregate specification. Used in op.aggregate to declare what to compute across grouped records.

Source: packages/slingshot-core/src/operations.ts

A typed config handle returned by defineConfig. Read with get() after the framework has loaded the values at boot.

Source: packages/slingshot-core/src/config.ts

Consume operation — atomically read and delete a record in a single call.

Used for one-time-use tokens, OTPs, magic links, and other single-claim resources. Optional expiry field check rejects records that have passed their TTL.

Source: packages/slingshot-core/src/operations.ts

Contact card data for contact-sharing messages. Stored in the contact field when type is 'contact'.

Source: packages/slingshot-core/src/content.ts

The core authentication adapter — required for every Slingshot auth deployment.

Provides the minimal set of operations needed to authenticate users with email/password credentials. All other tiers (OAuthAdapter, MfaAdapter, etc.) are optional and layer on top of this interface.

Remarks: Implementations live in adapter packages (e.g., @lastshotlabs/slingshot-postgres). The full composite AuthAdapter type is the union of all tiers.

Source: packages/slingshot-core/src/auth-adapter.ts

Aggregated counter entry in a MetricsSnapshot.

Source: packages/slingshot-core/src/metrics.ts

Dependencies for building the SlingshotEvents publisher: the definition registry and the event bus to emit through.

Source: packages/slingshot-core/src/eventPublisher.ts

Cron scheduler registry — persists the set of BullMQ scheduler names registered by the current deployment so the next deployment can identify and remove stale schedulers.

Remarks: When a scheduled job is renamed or removed between deployments, the old BullMQ RepeatableJob must be explicitly deleted or it will keep running forever. The cron registry solves this by saving the current deployment’s scheduler names at startup, then comparing against the previous deployment’s names to find stale ones.

Source: packages/slingshot-core/src/cronRegistry.ts

CSRF protection configuration for the auth plugin.

When enabled, the CSRF middleware verifies that the x-csrf-token header value matches the csrf_token cookie on state-changing requests (POST, PUT, PATCH, DELETE).

Remarks: CSRF protection is only meaningful for cookie-authenticated requests. Bearer token and M2M requests are inherently CSRF-safe and bypass the check. OAuth callback paths are always exempt to prevent breaking the redirect flow.

Source: packages/slingshot-core/src/csrf.ts

Options for cursor-paginated adapter list operations.

Pass cursor from a previous PaginatedResult.nextCursor to fetch the next page. Omit cursor to start from the beginning. Combine with sortDir to reverse traversal.

Source: packages/slingshot-core/src/entityConfig.ts

Default overrides for cursor-based pagination query parameters. Omitted fields fall back to framework defaults (limit=50, maxLimit=200).

Source: packages/slingshot-core/src/pagination.ts

Custom operation — escape hatch for operations that cannot be expressed declaratively.

Each backend key is an optional factory that receives the raw store handle and returns a typed callable. Only the factory for the active StoreType is called at runtime.

Standard vs. manual wiring: Standard config-driven factories require a callable factory for the active backend. Startup fails with UnsupportedEntityBackendError when it is absent. Applications that supply operation methods externally must use manual adapter wiring instead.

Route auto-mounting: Set http to have the entity plugin auto-mount an HTTP route for this operation. The method in http.method controls the HTTP verb; http.path overrides the URL segment (defaults to /{opName} in kebab-case). The route handler calls adapter[opName](body) — standard wiring verifies that the method can be built before the adapter or route is constructed.

Source: packages/slingshot-core/src/operations.ts

A data encryption key (DEK) entry for AES-256-GCM field encryption.

keyId is a short string embedded in the ciphertext envelope so that decryptField can identify which key to use when multiple keys are in rotation. key must be exactly 32 bytes for AES-256.

Remarks: Keep DEKs in a secret store (SSM, Vault, etc.) — never hard-code them. Configure multiple entries to support key rotation: the first entry is the active (encrypting) key; all entries are tried during decryption.

Source: packages/slingshot-core/src/crypto.ts

The response body shape produced by defaultValidationErrorFormatter. Clients can use details for per-field error display and requestId for support.

Source: packages/slingshot-core/src/context.ts

Input contract for definePackage(...).

Source: packages/slingshot-core/src/packageAuthoring.ts

Delivery adapter contract registered with slingshot-notifications.

Source: packages/slingshot-core/src/notificationsPeer.ts

Derive operation — compose results from multiple entity sources.

Queries each source in sources and merges the results according to merge. Useful for “feed” or “inbox” queries that pull from multiple entity types.

Source: packages/slingshot-core/src/operations.ts

A single data source for a DeriveOpConfig.

Specifies an entity to query (from) with match conditions (where). Optional traverse resolves a relation to a different entity.

Source: packages/slingshot-core/src/operations.ts

Domain route contract used by package-first authoring and compiled into framework routes.

Source: packages/slingshot-core/src/packageAuthoring.ts

Broker acknowledgement returned after durable transport acceptance.

Source: packages/slingshot-core/src/eventBus.ts

Narrow, untyped view of the event bus for string-keyed subscriptions.

Plugins that subscribe to dynamically named events (e.g. entity:${storageName}.created) cast the typed SlingshotEventBus to this interface rather than widening the global SlingshotEventMap. This keeps type widening local per rule 12.

Defined here once so every consumer imports the same shape (rule 6). Use Pick to narrow further when a module only needs emit or only needs on/off.

Source: packages/slingshot-core/src/eventBus.ts

Resolved link preview data. Stored in the embeds field of content entities. Populated asynchronously by slingshot-embeds after content creation.

Clients render embeds as preview cards below the content body.

Source: packages/slingshot-core/src/content.ts

Cross-package handle to the embeds plugin’s URL unfurling capability.

Source: packages/slingshot-core/src/embedsPeer.ts

Enterprise adapter methods — required when M2M clients, the admin user-list API, or password-reuse prevention is configured.

All methods are individually optional and guarded by their respective config flags. Implement only the methods needed for your configuration.

Source: packages/slingshot-core/src/auth-adapter.ts

The typed adapter interface generated for an entity by slingshot-data.

Provides CRUD operations with full type inference from the entity’s field definitions. The create, update, delete, and list methods handle soft-delete logic transparently when the entity is configured with softDelete.

Source: packages/slingshot-core/src/entityConfig.ts

Coordinates for locating an entity adapter within plugin state.

Source: packages/slingshot-core/src/pluginStateTypes.ts

Exhaustive semantic profile for one standard entity backend.

Source: packages/slingshot-core/src/entityCapabilities.ts

One semantic capability required by an entity or named operation.

Source: packages/slingshot-core/src/entityCapabilities.ts

Top-level entity channel configuration.

Attached to an EntityConfig to declare named real-time channels and their subscription auth, permissions, middleware, and event-forwarding rules.

Source: packages/slingshot-core/src/entityChannelConfig.ts

Configuration for a single named channel on an entity.

Channels create WebSocket rooms with the pattern {storageName}:{entityId}:{channelName}. Clients subscribe by sending { type: 'subscribe', room: '{storageName}:{entityId}:{channelName}' }. The framework evaluates auth, permission, and middleware in that order when a subscribe message is received, then registers the client for event forwarding.

Remarks: All fields are optional — an empty declaration {} creates a public channel with no auth, no permission check, no middleware, and no forwarded events. Add only the fields you need. middleware entries are resolved from the entity plugin config’s middleware map at startup; referencing an unknown middleware key is a startup-time error.

Source: packages/slingshot-core/src/entityChannelConfig.ts

The complete entity definition — the single source of truth for an entity’s schema, persistence, and route/channel configuration.

Pass this to defineEntity() which validates it and derives _pkField and _storageName. The resolved result is deep-frozen and registered with the entity registry.

Source: packages/slingshot-core/src/entityConfig.ts

Entity-level DTO config — a flat map of mapper names to mapper functions.

The reserved default key is applied when a route does not name a variant. Any other key becomes a named variant selectable via routes.<op>.dto (for entity CRUD routes) or responses[status].dto (for custom ops and domain routes). Single-shape entities use only { default: ... }.

Source: packages/slingshot-core/src/entityConfig.ts

A page of results from a cursor-paginated adapter list operation.

nextCursor is present when more records exist beyond this page. Pass it back as cursor in the next call to advance the page.

Source: packages/slingshot-core/src/entityConfig.ts

Declares the permission resource type and role/action mappings for an entity.

When present on EntityRouteConfig.permissions, the framework auto-registers this resource type in the PermissionRegistry at startup, making all declared actions available for grant assignment and role-based default wiring.

Remarks: scopeField gates grants to a specific field value — for example, setting scopeField: 'tenantId' means grants are scoped per tenant rather than globally. roles provides default role → actions mappings that the framework seeds into the permission store on first run. Use '*' as the sole entry in an actions array to grant all declared actions to that role. At least one entry in actions is required (enforced by the schema).

Source: packages/slingshot-core/src/entityRouteConfig.ts

Runtime registry of resolved entity configs that plugins query to discover entities (search, schema, admin, migrations).

Source: packages/slingshot-core/src/entityRegistry.ts

Declarative route configuration for a single entity.

Attached to an EntityConfig to configure auth, permissions, rate limits, events, middleware, retention, and cascades for generated CRUD routes without writing middleware by hand.

Remarks: defaults applies to all operations unless overridden. Individual operation configs (e.g., create, list) are merged on top of defaults — specific keys win.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Declarative row-level isolation for standard CRUD routes.

Remarks: Each entry binds a server-side source value to an entity field and enforces that binding on the selected CRUD operations. create writes the scoped field from the resolved source, list merges the binding into the adapter filter, and get / update / delete apply the binding atomically as an additional adapter filter. A mismatch returns 404, not 403.

Remarks: If an update request body contains any scoped field, the request is rejected with HTTP 400 and { error: 'scoped_field_immutable', field }.

Remarks: Multiple entries may be supplied as an array and are enforced with AND semantics. A dataScope declaration without any auth-enabled route is rejected at startup by the Zod schema.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Declarative reference to a policy resolver.

The resolver field accepts either an opaque string key (legacy) or a typed PolicyToken from definePolicy(...). Tokens give compile-time guarantees that the registered resolver and the route reference name the same key.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Entity-level search configuration.

Declares what’s searchable on an entity. The search plugin provides the engine; the entity declares which fields participate, how they’re weighted, and what sync strategy to use.

Source: packages/slingshot-core/src/entityConfig.ts

Consumer-configurable storage convention overrides for an entity.

Passed via conventions on EntityConfig. Allows consumers to customize how records are keyed in Redis, how IDs are generated, and how fields are updated without forking adapter code.

All properties are optional. When omitted, the built-in defaults apply:

  • Redis key format: ${storageName}:${appName}:${pk}
  • ID generation: 'uuid', 'cuid', 'now' (built-in sentinels)
  • On-update: 'now' (built-in sentinel)

Source: packages/slingshot-core/src/entityConfig.ts

Storage-level field name overrides for backend adapters.

These control how domain fields are mapped to physical storage fields. All fields have sensible defaults when omitted.

Source: packages/slingshot-core/src/entityConfig.ts

Per-backend storage configuration overrides for an entity.

Use these to customise table/collection names and other backend-specific settings without changing the entity’s canonical name or namespace.

Source: packages/slingshot-core/src/entityConfig.ts

Consumer-configurable system field names for an entity.

Allows consumers to rename framework-assumed field names to match their domain model. All fields have sensible defaults when omitted.

Source: packages/slingshot-core/src/entityConfig.ts

Optional TTL (time-to-live) for entity records.

When set, adapters that support TTL-based expiry (Redis, memory) will automatically expire records after defaultSeconds. SQL adapters that don’t support native TTL must implement periodic cleanup separately.

Source: packages/slingshot-core/src/entityConfig.ts

Opt-in optimistic-concurrency configuration for an entity.

Source: packages/slingshot-core/src/entityConfig.ts

Per-write optimistic-concurrency options accepted by entity adapters.

Source: packages/slingshot-core/src/entityConfig.ts

Value returned from onError that overrides how an invocation failure is reported (replacement error, status, body, or suppression).

Source: packages/slingshot-core/src/functions.ts

The permission evaluation scope — narrows which grants are considered effective. Omitting a field means “match any value at that level”.

Source: packages/slingshot-core/src/permissions.ts

Shared adapter options for runtime event validation and custom durable serialization.

Source: packages/slingshot-core/src/eventSerializer.ts

Declares a publishable event: its owner, exposure surfaces, payload schema, and scope/authorization/projection logic.

Source: packages/slingshot-core/src/eventTypes.ts

Registry of EventDefinitions keyed by event name, freezable once all plugins have registered their events.

Source: packages/slingshot-core/src/eventDefinitionRegistry.ts

Options for createEventDefinitionRegistry, including an optional schema registry to mirror payload schemas into.

Source: packages/slingshot-core/src/eventDefinitionRegistry.ts

A published event: its key, typed payload, and EventEnvelopeMeta delivery metadata.

Source: packages/slingshot-core/src/eventTypes.ts

Delivery metadata stamped onto every published event envelope (identity, timing, owner, exposure, scope, and request correlation).

Source: packages/slingshot-core/src/eventTypes.ts

Request- or job-scoped context passed at publish time so a definition can resolve scope and stamp envelope metadata.

Source: packages/slingshot-core/src/eventTypes.ts

Registry for event payload schemas. Plugins register Zod schemas for their events during setup.

Source: packages/slingshot-core/src/eventSchemaRegistry.ts

Ownership and resource context resolved from an event payload, used to authorize external subscribers.

Source: packages/slingshot-core/src/eventTypes.ts

Controls how event payloads are encoded for durable transport (Kafka topics, BullMQ queues) and decoded on the consumer side.

Non-durable listeners always receive the original in-process object — the serializer is only invoked on durable produce and consume paths.

Source: packages/slingshot-core/src/eventSerializer.ts

Identifies the consumer an event would be delivered to when checking subscriber authorization.

Source: packages/slingshot-core/src/eventTypes.ts

Result of adapting a stored payload to the current governed event version.

Source: packages/slingshot-core/src/eventVersionRegistry.ts

Converts one governed event payload version into the next registered version.

Source: packages/slingshot-core/src/eventVersionRegistry.ts

Immutable lookup contract for governed event-version adapters.

Source: packages/slingshot-core/src/eventVersionRegistry.ts

Exists operation — check whether at least one record satisfies a field match.

More efficient than lookup when you only need a boolean result. Optional check fields narrow the test beyond the primary match.

Source: packages/slingshot-core/src/operations.ts

Resolved field definition — the normalised shape stored in EntityConfig.fields.

Created by the field.*() builders. Plugins should treat this as opaque.

Generic parameters preserve literal types for precise InferCreateInput narrowing:

  • T — the FieldType token
  • IsOptionaltrue or false literal
  • Default — the exact default value type (e.g. 'uuid', 'now', 'member', undefined)
  • OnUpdate'now' or undefined

All parameters have wide defaults so existing FieldDef usages without type params continue to compile without changes.

Source: packages/slingshot-core/src/entityConfig.ts

Options shared by all field.*() builders.

Control optional/required status, default values, immutability, and primary key designation.

Source: packages/slingshot-core/src/entityConfig.ts

Maps FieldType tokens to their corresponding TypeScript types.

Used by InferEntity, InferCreateInput, and InferUpdateInput to derive entity types from field definitions without repetition.

Source: packages/slingshot-core/src/entityConfig.ts

Field update operation — selectively update a subset of fields on a matched record.

More targeted than a full update — only the fields listed in set can be mutated. Useful for operations that update one attribute without overwriting others (e.g., mark as read).

Source: packages/slingshot-core/src/operations.ts

Case-insensitive substring filter: field value must contain the string.

Source: packages/slingshot-core/src/operations.ts

Greater-than filter operator: { $gt: value } — supports 'now' for date comparisons.

Source: packages/slingshot-core/src/operations.ts

Greater-than-or-equal filter operator. Supports 'now' for date comparisons.

Source: packages/slingshot-core/src/operations.ts

Inclusion filter: field value must be in the provided array.

Source: packages/slingshot-core/src/operations.ts

Less-than filter operator. Supports 'now' for date comparisons.

Source: packages/slingshot-core/src/operations.ts

Less-than-or-equal filter operator. Supports 'now' for date comparisons.

Source: packages/slingshot-core/src/operations.ts

Not-equal filter operator: { $ne: value }

Source: packages/slingshot-core/src/operations.ts

Exclusion filter: field value must NOT be in the provided array.

Source: packages/slingshot-core/src/operations.ts

Lifecycle hooks for a functions runtime.

Source: packages/slingshot-core/src/functions.ts

A functions runtime that wraps handlers into trigger-platform entrypoints and exposes the context and shutdown lifecycle.

Source: packages/slingshot-core/src/functions.ts

Configuration for a functions runtime: the handler manifest, optional runtime, lifecycle hooks, and timeout budgets.

Source: packages/slingshot-core/src/functions.ts

Aggregated gauge entry in a MetricsSnapshot.

Source: packages/slingshot-core/src/metrics.ts

Options for generateFromSchema.

Source: packages/slingshot-core/src/faker/generateFromSchema.ts

Geo search configuration. Both fields must be number type.

Source: packages/slingshot-core/src/entityConfig.ts

Object form of groupBy with optional date truncation.

When truncate is provided, the raw field value is converted to a date and truncated to the specified granularity before grouping. This allows grouping date fields by month, day, etc., without requiring a separate denormalized field.

Source: packages/slingshot-core/src/operations.ts

A record of a user’s membership in a group.

Membership carries optional per-member roles that extend the group’s baseline roles. tenantId is denormalised from the group at insert time for efficient per-tenant queries.

Source: packages/slingshot-core/src/auth-adapter.ts

A user group record stored by GroupsAdapter.

Groups aggregate users with shared baseline roles. A group is either app-wide (tenantId = null) or scoped to a specific tenant. The tenantId is immutable after creation — it cannot be moved between tenants.

Source: packages/slingshot-core/src/auth-adapter.ts

Resolves the group memberships for a user.

Provided to the permissions evaluator so group-based grants can be expanded into per-user effective grants without the evaluator depending on the GroupsAdapter directly.

Source: packages/slingshot-core/src/permissions.ts

Group management adapter methods — required when auth.groups is configured.

Groups aggregate users with shared baseline roles. Members inherit the group’s roles plus any per-member extra roles. getEffectiveRoles returns the merged role set.

Source: packages/slingshot-core/src/auth-adapter.ts

Arguments passed to guards, handlers, and after hooks.

Every callback in the handler pipeline receives the same HandlerArgs instance, giving uniform access to validated input, the app context, invocation metadata, and the handler’s registered name.

Source: packages/slingshot-core/src/handler.ts

Configuration for defineHandler.

Describes the handler’s name, input/output schemas, optional guard pipeline, optional after-hook pipeline, and the core handler function.

Source: packages/slingshot-core/src/handler.ts

Invocation metadata for a transport-agnostic handler call.

Every handler invocation receives a HandlerMeta describing the request context: who made the call, tracing identifiers, and optional HTTP details. Guards, after-hooks, and the handler itself all share the same meta instance.

Source: packages/slingshot-core/src/handler.ts

App-level health config — declared on defineApp({ health: { ... } }).

Source: packages/slingshot-core/src/observability/health.ts

Implemented by any component that wants to participate in framework-level health aggregation.

Source: packages/slingshot-core/src/observability/health.ts

A user-defined readiness probe. Registered via defineApp({ health: { indicators: [...] } }) and run by the /health/ready route on every request.

Source: packages/slingshot-core/src/observability/health.ts

Context passed to a health indicator’s check() function.

ctx is the live Slingshot context — use it to reach databases, caches, queues, or any plugin state needed by the probe.

Source: packages/slingshot-core/src/observability/health.ts

Result returned from a health indicator’s check() function.

Return { status: 'ok' } when the dependency is responding normally; return 'degraded' for “responding but slow / partial”; return 'unhealthy' (or throw) for “down”. Any thrown error is treated as unhealthy with the error message captured in message.

Source: packages/slingshot-core/src/observability/health.ts

Per-component health snapshot. Aggregators combine many of these into a single response.

Source: packages/slingshot-core/src/observability/health.ts

Out-of-request hook services. Mirrors the accessor surface PackageDomainRouteContext exposes to request-scoped route handlers, plus the raw pluginState map as an escape hatch for callers that need slots no typed accessor yet covers.

Always construct via buildHookServices() at the hook call site — never fabricate one by hand. Hook payloads in plugin lifecycle callbacks should declare services: HookServices (or services?: HookServices for callbacks that can fire from worker isolates that cannot reach the app).

Source: packages/slingshot-core/src/hookServices.ts

Storage contract for idempotency key deduplication.

When a client retries a mutating request with the same Idempotency-Key header, the idempotency middleware looks up the cached response via this adapter and returns it instead of executing the handler again.

Remarks: Implementations must respect the ttlSeconds argument in set() — records should expire automatically after the configured TTL. The framework sets a default TTL of 24 hours for idempotency records.

Source: packages/slingshot-core/src/idempotencyAdapter.ts

Idempotency settings for a wrapped trigger: dedup TTL, key scope, custom key derivation, and payload fingerprinting.

Source: packages/slingshot-core/src/functions.ts

Normalised identity profile sourced from an OAuth provider.

Populated by OAuthAdapter.findOrCreateByProvider() when a user authenticates via an external provider. All fields are optional — each provider exposes different claim sets.

Source: packages/slingshot-core/src/auth-adapter.ts

Maps raw identity input into a canonical Actor.

Configured on the app via CoreRegistrar.setIdentityResolver() or the identity.resolver option in createApp() / createServer(). When no custom resolver is registered the framework uses the default resolver.

Source: packages/slingshot-core/src/identity.ts

Identity values extracted from the request, passed to the configured IdentityResolver to produce a canonical Actor.

Field names map to the actor kind they produce in the default resolver:

  • userId'user' actor
  • serviceAccountId'service-account' actor (M2M / OAuth client)
  • apiKeyId'api-key' actor (static bearer-token client)

Custom auth integrations populate whichever of these fields they recognize before invoking the resolver.

Source: packages/slingshot-core/src/identity.ts

Increment (or decrement) a numeric field on a specific record.

The record is looked up by primary key. The named field is increased by by (default 1). Pass a negative value for by to decrement. All backends perform the increment atomically where the store supports it (Postgres uses SET field = field + $n, Mongo uses $inc, memory/Redis use read-modify-write).

Source: packages/slingshot-core/src/operations.ts

A compound index definition for an entity.

Created via the index() helper and listed in EntityConfig.indexes. Adapters use these definitions to create backing store indexes at startup.

Source: packages/slingshot-core/src/entityConfig.ts

In-process MetricsEmitter plus a snapshot() accessor.

Source: packages/slingshot-core/src/metrics.ts

Returned from beforeInvoke to short-circuit an invocation, optionally supplying the response to return instead.

Source: packages/slingshot-core/src/functions.ts

Options for directly invoking a SlingshotHandler outside of a transport layer (e.g. from tests, CLI commands, or inter-handler calls).

Source: packages/slingshot-core/src/handler.ts

Cumulative drop telemetry for connector outbound publishes and inbound dedup.

Source: packages/slingshot-core/src/kafkaConnectors.ts

Programmatic lifecycle contract for Kafka connectors that bridge the internal bus to external Kafka topics.

Source: packages/slingshot-core/src/kafkaConnectors.ts

Aggregate health for the Kafka connector bridge.

Source: packages/slingshot-core/src/kafkaConnectors.ts

Health snapshot for one inbound Kafka connector.

Source: packages/slingshot-core/src/kafkaConnectors.ts

Health snapshot for one outbound Kafka connector.

Source: packages/slingshot-core/src/kafkaConnectors.ts

Filters and pagination options for listing users via the admin API.

Source: packages/slingshot-core/src/adminProvider.ts

Paginated list of managed user records returned by ManagedUserProvider.listUsers().

Source: packages/slingshot-core/src/adminProvider.ts

Geolocation data for location-sharing messages. Stored in the location field when type is 'location'.

Source: packages/slingshot-core/src/content.ts

Free-form structured fields attached to a log line.

Source: packages/slingshot-core/src/observability/logger.ts

Structured logger handle. Implementations must not throw from any method.

Source: packages/slingshot-core/src/observability/logger.ts

Lookup operation — find one or many records by matching field values.

fields maps entity field names to 'param:x' references or literals. returns: 'one' produces Entity | null; returns: 'many' produces a paginated list.

Source: packages/slingshot-core/src/operations.ts

A machine-to-machine (M2M) client record used for service-to-service authentication.

M2M clients authenticate with a clientId + clientSecret and receive a short-lived access token scoped to the declared scopes. Used by background workers, CI pipelines, and internal services that cannot use user sessions.

Source: packages/slingshot-core/src/auth-adapter.ts

A swappable email template renderer.

Implement this interface to connect any template engine (Handlebars, MJML, React Email, etc.) to the Slingshot mail infrastructure. Registered via the mail plugin configuration.

Source: packages/slingshot-core/src/mail.ts

Capabilities advertised by a ManagedUserProvider.

The admin UI uses these flags to show/hide features based on what the underlying provider supports. Always call getCapabilities() before attempting optional operations like suspendUser or revokeSession.

Source: packages/slingshot-core/src/adminProvider.ts

A pluggable managed-user provider for the slingshot admin API.

Abstracts over the auth adapter to provide a normalised user management interface. The admin plugin discovers registered providers from ctx.pluginState and uses the capabilities API to determine which admin operations are available.

Remarks: Optional methods (suspendUser, deleteUser, etc.) are only called when getCapabilities() returns true for the corresponding flag. Never call them without checking capabilities first.

Source: packages/slingshot-core/src/adminProvider.ts

A user record as exposed by the admin API. Normalised across auth providers — source-specific fields are in metadata.

Source: packages/slingshot-core/src/adminProvider.ts

Tenant scope applied to admin managed-user operations.

Source: packages/slingshot-core/src/adminProvider.ts

Pluggable metrics sink for plugin-emitted counters, gauges, and timings.

Implementations must be safe to call from hot paths — no I/O, no allocation spikes, and no exceptions. Failed writes should be swallowed; metrics are best-effort observability, not critical correctness.

Remarks: Naming convention — names should follow <package>.<area>.<metric> form (e.g. search.query.count, notifications.delivery.duration). Labels carry dimensions (provider, status, tenant). Keep label cardinality low — every unique label combination is a distinct time-series.

Source: packages/slingshot-core/src/metrics.ts

Serializable point-in-time snapshot of an in-process metrics emitter.

Source: packages/slingshot-core/src/metrics.ts

MFA adapter methods — required when auth.mfa is configured.

Manages TOTP secrets, MFA-enabled flags, and backup/recovery codes. Called by the auth plugin during MFA setup and verification flows.

Source: packages/slingshot-core/src/auth-adapter.ts

Builder contract published by slingshot-notifications to peer plugins.

Source: packages/slingshot-core/src/notificationsPeer.ts

Event payload delivered to notification delivery adapters.

Source: packages/slingshot-core/src/notificationsPeer.ts

Normalized notification record shape shared across packages.

This is the neutral contract feature plugins use for formatter registration, delivery adapters, and source-scoped notification creation.

Source: packages/slingshot-core/src/notificationsPeer.ts

Input accepted by a source-scoped notification builder.

Source: packages/slingshot-core/src/notificationsPeer.ts

Batch notification input accepted by a source-scoped builder.

Source: packages/slingshot-core/src/notificationsPeer.ts

OAuth adapter methods — required when auth.oauth.providers is configured.

Handles the server-side storage of OAuth provider linkages. The auth plugin calls these methods after successfully validating an OAuth callback from a provider.

Source: packages/slingshot-core/src/auth-adapter.ts

Default overrides for offset-based pagination query parameters. All fields are optional — omitted fields fall back to framework defaults (limit=50, offset=0, maxLimit=200).

Source: packages/slingshot-core/src/pagination.ts

Arguments passed to the onError hook describing a failed invocation, including the error, its ErrorKind, and correlation metadata.

Source: packages/slingshot-core/src/functions.ts

Storage contract for operation-level idempotency dedupe.

Remarks: Note: the public re-export from @lastshotlabs/slingshot-core aliases this interface to OperationIdempotencyAdapter to avoid clashing with the existing HTTP IdempotencyAdapter. Within this module the canonical name is IdempotencyAdapter.

Source: packages/slingshot-core/src/idempotency/index.ts

Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.

Source: packages/slingshot-core/src/packageAuthoring.ts

Publish and consume a typed cross-package contract without adapter bags or singleton registries.

Source: packages/slingshot-core/src/packageAuthoring.ts

Typed capability lookup helpers exposed to package domain routes.

Source: packages/slingshot-core/src/packageAuthoring.ts

Provider-owned package public contract. Binds capabilities and public entity refs to a single package, validates capability ownership at definePackage(...) time, and carries identity metadata on every ref/capability it produces so the framework can validate the cross-package graph at boot.

Source: packages/slingshot-core/src/packageAuthoring.ts

Snapshot of contract metadata attached to packages produced by Matches.definePackage(...). Boot validation reads these to verify cross-package wiring.

Source: packages/slingshot-core/src/packageAuthoring.ts

Full handler context available to package-authored domain routes.

Source: packages/slingshot-core/src/packageAuthoring.ts

Lookup helper for framework-managed entity adapters owned by the app.

Source: packages/slingshot-core/src/packageAuthoring.ts

Lightweight typed entity handle used for package-local and cross-package adapter lookups.

Source: packages/slingshot-core/src/packageAuthoring.ts

Static inspection output for a package’s effective modules and capability graph.

Source: packages/slingshot-core/src/packageAuthoring.ts

Canonical request metadata exposed to package-authored route handlers.

Source: packages/slingshot-core/src/packageAuthoring.ts

A page of results from a cursor-paginated adapter list operation.

nextCursor is present when more records exist beyond this page. Pass it back as cursor in the next call to advance the page.

Source: packages/slingshot-core/src/entityConfig.ts

Cursor pagination configuration for an entity’s list operation.

cursor.fields are the tie-breaking fields used to construct stable, opaque cursors. Typically ['createdAt', 'id'] for stable time-ordered pagination.

Source: packages/slingshot-core/src/entityConfig.ts

Pagination options for auth adapter list operations.

Source: packages/slingshot-core/src/auth-adapter.ts

Server-truth projection of a content body into the entity’s sidecar fields. The runtime function lives in ./contentParser to keep this module’s value surface minimal; the result type is declared here so type-only consumers don’t pull the parser in.

See import('./contentParser').parseBody.

Source: packages/slingshot-core/src/content.ts

Result of parsing a content body for inline tokens.

Segments preserve order and duplicates (for rendering). Derived arrays are deduped (for notification routing / indexing).

Source: packages/slingshot-core/src/content.ts

Parsed and clamped cursor pagination parameters ready for use in a query.

Source: packages/slingshot-core/src/pagination.ts

Parsed and clamped offset pagination parameters ready for use in a query.

Source: packages/slingshot-core/src/pagination.ts

High-level permission evaluator that answers can(subject, action, scope) queries.

The evaluator fetches effective grants for the subject (expanding group memberships via GroupResolver), resolves the actions granted by each role using PermissionRegistry, and applies deny-wins semantics.

Source: packages/slingshot-core/src/permissions.ts

A single row in the permissions store — a durable record that a subject holds (or is denied) specific roles on a resource or scope.

Remarks: Grants cascade through four levels of specificity: 1. Global (tenantId=null, resourceType=null, resourceId=null) 2. Tenant-wide (tenantId=T, resourceType=null, resourceId=null) 3. Type-wide (tenantId=T, resourceType=RT, resourceId=null) 4. Specific resource (tenantId=T, resourceType=RT, resourceId=RID)

Remarks: Deny effects at any level override allows from any other level.

Source: packages/slingshot-core/src/permissions.ts

In-memory registry that maps resource types to their role/action definitions.

Created once per app instance during bootstrap. Plugins register their resource types during setupPost. The permissions evaluator queries this registry when resolving can() checks.

Source: packages/slingshot-core/src/permissions.ts

Storage adapter for the slingshot-permissions plugin.

Implementations are responsible for persisting PermissionGrant records and answering effective-grant queries. A grant is “effective” when:

  • It has not been revoked (revokedAt is null/undefined)
  • It has not expired (expiresAt is null or in the future)
  • Its stored scope is satisfied by the evaluation scope

Remarks: Follow the swappable provider pattern: add a new implementation file and a case in the factory dispatch — never modify this interface for adapter-specific needs.

Source: packages/slingshot-core/src/permissions.ts

Runtime state stored under PERMISSIONS_RUNTIME_KEY by the slingshot-permissions plugin after it initialises.

Source: packages/slingshot-core/src/permissions.ts

Pipe operation — chain multiple operations where each step feeds into the next.

The output of each step is available to the next via 'result:field' references in input. Useful for multi-stage workflows (e.g., create + lookup + enrich).

Source: packages/slingshot-core/src/operations.ts

A single step within a PipeOpConfig.

The input map allows passing values from the previous step’s result using 'result:field' references, enabling sequential operation chaining.

Source: packages/slingshot-core/src/operations.ts

Context passed to the seed() lifecycle phase.

Provides seedInput (the raw declarative seed config; each plugin/package reads the keys it owns) and seedState (a shared cross-plugin map for passing created IDs between plugins during seeding). Plugins access runtime services through pluginState on the app context.

Source: packages/slingshot-core/src/plugin.ts

Context object passed to all plugin lifecycle methods.

Using an options object instead of positional parameters means adding a new field in the future is non-breaking — plugins that don’t need the new field simply don’t destructure it.

Source: packages/slingshot-core/src/plugin.ts

Any object that carries a PluginStateMap.

Source: packages/slingshot-core/src/pluginStateTypes.ts

Typed handle for a plugin-state slot.

Created by definePluginStateKey. Use with publishPluginState and readPluginState to publish and read plugin state without as Foo casts at the read site. The phantom generic __type carries the value type through the type system.

Source: packages/slingshot-core/src/pluginState.ts

The structured return value of a policy resolver.

Resolvers may return a plain boolean for the simple allow/deny case; the framework normalizes true{ allow: true } and false{ allow: false, status: 403 }. Return a PolicyDecision explicitly when you want to:

  • Surface a reason for audit logs (not leaked to the client body).
  • Override the rejection status code to 404 for leak-prevention (when the existence of the record itself is sensitive).
  • Attach a structured metadata blob for downstream middleware.

Remarks: The HTTP response body on deny is always a generic { error: 'forbidden' } or { error: 'not found' }. The reason field is recorded server-side only — via event bus entity:policy.denied and optional logger integration. Never echoed to the client.

Source: packages/slingshot-core/src/entityRouteConfig.ts

The structured input passed to a policy resolver on every check.

TRecord and TInput are the entity’s record and create/update input types. Framework default is unknown — consumers tighten the generics in their own resolver code via PolicyResolver<MyRecord, MyInput>.

Remarks: - userId is non-null: the framework only invokes policy after the auth step has succeeded. If auth is not userAuth or bearer, declaring permission.policy is a startup error (see the superRefine cross-field check). - tenantId is null when the app is not multi-tenant; resolvers should tolerate null. - c is the Hono Context. Resolvers MAY read request headers, metadata, or attach breadcrumbs via c.set('policyTrace', ...). Resolvers MUST NOT mutate c.req or write response bodies — returning a decision is the only allowed side effect.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Typed bundle of (key, resolver) produced by definePolicy(...).

Pass the token directly to registerEntityPolicy(...) and reference the same token value in EntityRoutePolicyConfig.resolver to get compile-time consistency between registration and use — typos in the policy key become compile errors instead of startup errors.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Brand-only reference to a policy token. Used at the route-config field type so the framework can detect tokens without forcing the route config to know the resolver’s record/input types.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Postgres connection bundle passed through StoreInfra to repository factories.

The concrete implementation (DrizzlePostgresDb) lives in @lastshotlabs/slingshot-postgres and satisfies this interface at runtime. db is typed as unknown in core to avoid a hard dependency on drizzle-orm — import from slingshot-postgres when you need the full NodePgDatabase type for query building.

Remarks: Always obtain this bundle via infra.getPostgres() inside a repository factory. Do not call infra.getPostgres() at module load time — the Postgres pool is initialised lazily and may not be ready until the framework bootstrap completes.

Source: packages/slingshot-core/src/storeInfra.ts

Outcome of a Postgres connectivity probe: success flag, latency, timestamp, and any error message.

Source: packages/slingshot-core/src/postgresRuntime.ts

Per-pool runtime that records query timings/failures and produces PostgresPoolStatsSnapshots.

Source: packages/slingshot-core/src/postgresRuntime.ts

Immutable point-in-time view of a Postgres pool’s connection counts and query/error statistics.

Source: packages/slingshot-core/src/postgresRuntime.ts

Fluent builder returned by contract.publicEntity(module). Consumers must pick an exposure mode — readonly([...]), as<TShape>(), or unsafeFullAdapter() — before the candidate can be passed to contract.publicEntities({...}).

Source: packages/slingshot-core/src/packageAuthoring.ts

Output of a public entity exposure decision. Only valid input to Matches.publicEntities(...). Raw entity modules are deliberately rejected at the type level: publishing an entity must be an explicit decision paired with an exposure mode (readonly, as, or unsafeFullAdapter).

Source: packages/slingshot-core/src/packageAuthoring.ts

Metadata captured when a package contract publishes an entity ref. runtimeEnforced is true for readonly mode (the framework wraps the adapter to expose only the declared methods) and false for as and unsafeFullAdapter modes, where the runtime returns the full underlying adapter.

Source: packages/slingshot-core/src/packageAuthoring.ts

Single published capability record carried by a contract metadata snapshot.

Source: packages/slingshot-core/src/packageAuthoring.ts

Single published entity record carried by a contract metadata snapshot.

Source: packages/slingshot-core/src/packageAuthoring.ts

Cross-package handle for resolving and updating interactive message components published by a peer package.

Source: packages/slingshot-core/src/publishedInteractionsPeer.ts

Published capability resolver registered by a package during bootstrap.

Source: packages/slingshot-core/src/packageAuthoring.ts

Cross-package handle for registering per-notification-type push message formatters with the push package.

Source: packages/slingshot-core/src/pushPeer.ts

Shape of a formatted push notification: title plus optional body, data, icon, badge, and URL.

Source: packages/slingshot-core/src/pushPeer.ts

Common lifecycle contract shared by domain-specific queue implementations (mail, webhooks, etc.). Plugins reference this type in teardown and health-check code that does not need to know the domain-specific start() signature.

Each domain queue extends this interface and adds its own start(arg) overload.

Source: packages/slingshot-core/src/queueLifecycle.ts

Snapshot of a quoted message or reply. Populated at creation time. The snapshot does NOT update if the quoted content is later edited.

Source: packages/slingshot-core/src/content.ts

Arguments passed to the onRecordError hook when a single record within a batch trigger fails.

Source: packages/slingshot-core/src/functions.ts

Per-record processing outcome.

Source: packages/slingshot-core/src/functions.ts

Canonical Redis client interface used across all slingshot packages.

Concrete implementations (ioredis, Upstash Redis, etc.) satisfy this contract. Typed as an interface rather than a class so that any Redis-compatible client can be used without an adapter layer.

Remarks: getdel is optional because it is not supported by all Redis versions (requires Redis 6.2+). Framework code that calls getdel should fall back to GET+DEL when it is absent.

Source: packages/slingshot-core/src/redis.ts

Informational relation metadata for an entity field.

Relations are NOT automatically joined by adapters — they are metadata hints for code generation, admin UIs, and schema documentation tools. Joins must be done manually in operation configs (op.derive, op.lookup) or at the application layer.

Source: packages/slingshot-core/src/entityConfig.ts

The rendered output of an email template. Contains the final HTML body, an optional plain-text alternative, and an optional subject line.

Source: packages/slingshot-core/src/mail.ts

A typed request-scope handle. The T parameter is the type of the value produced by factory and consumed by getRequestScoped.

Construct via defineRequestScope. The __brand field exists only at the type level so callers of getRequestScoped get the right value type; it is never read at runtime.

Source: packages/slingshot-core/src/requestScope.ts

Context passed to a request scope’s factory and cleanup functions.

request is the live Hono context; use it for headers, params, the actor, or other per-request data. The Slingshot context can be reached via getSlingshotCtx(request) for app-wide handles.

Source: packages/slingshot-core/src/requestScope.ts

Internal storage slot stashed on the Hono context. Holds the registered scope definitions plus the per-request map of initialized values.

Source: packages/slingshot-core/src/requestScope.ts

The validated, frozen output of defineEntity().

Extends EntityConfig with derived fields computed at definition time:

  • _pkField — the primary key field name
  • _storageName — the table/collection name with namespace applied
  • _systemFields — resolved audit, ownership, and tenant field names
  • _storageFields — resolved Mongo PK and TTL column names
  • _conventions — resolved storage convention overrides (Redis key, ID gen, etc.)

The object is deeply frozen — all nested configs are immutable after defineEntity() returns.

Source: packages/slingshot-core/src/entityConfig.ts

Resolved storage conventions attached to ResolvedEntityConfig._conventions.

Mirrors EntityStorageConventions with the same optional shape. undefined fields mean “use built-in behavior”. The resolved object is frozen at definition time and consumed by all backend adapters.

Source: packages/slingshot-core/src/entityConfig.ts

Resolved (defaulted) storage field mapping attached to ResolvedEntityConfig.

All fields are guaranteed non-null — defaults are applied at definition time by defineEntity(). Backend adapters read these resolved names instead of hardcoding storage-level field conventions.

Source: packages/slingshot-core/src/entityConfig.ts

Resolved (defaulted) system fields attached to ResolvedEntityConfig.

All fields are guaranteed non-null — defaults are applied at definition time by defineEntity(). Adapters and route builders read these resolved names instead of hardcoding first-party conventions.

Source: packages/slingshot-core/src/entityConfig.ts

Normalized optimistic-concurrency metadata attached by defineEntity.

Source: packages/slingshot-core/src/entityConfig.ts

The resolved result of pairing an entity config with its named operation configs.

Produced by op.define() (in slingshot-data) and consumed by the executor and codegen layers. The operations map is keyed by operation name (e.g. 'getByRoom').

Source: packages/slingshot-core/src/operations.ts

Resolved persistence repositories for the application instance.

Created by resolveFrameworkPersistence() during server bootstrap and wired into SlingshotContext by createApp(). All repositories are instance-scoped — no shared module-level state across app instances.

Remarks: Access these repositories via ctx.persistence.* in plugin setupPost hooks and in framework middleware. Never access them before createApp() completes.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Effective delivery preferences resolved for one notification dispatch.

Source: packages/slingshot-core/src/notificationsPeer.ts

Resolved store selections — which backing store each framework subsystem uses.

Defined here (not in framework internals) so plugins can reference the type without importing from the framework’s private modules.

Source: packages/slingshot-core/src/context/frameworkConfig.ts

Declares the roles and actions available for a single resource type.

Plugins call PermissionRegistry.register() during setupPost to declare which actions exist and which roles imply which actions. The evaluator uses this to resolve can(subject, action, scope) queries.

Source: packages/slingshot-core/src/permissions.ts

Role management adapter methods — required when auth.roles, auth.defaultRole, or tenancy is configured.

Manages app-wide and tenant-scoped roles for users. Roles are stored as string arrays and included in the JWT claims when tokens are issued.

Source: packages/slingshot-core/src/auth-adapter.ts

Per-room message persistence configuration. Supplied via ResolvedPersistence.configureRoom() during plugin setupPost.

Source: packages/slingshot-core/src/wsMessages.ts

A declarative cascade that batch-updates or batch-deletes related entity records when a specified bus event fires.

Common use-case: when an organisation is deleted, cascade-delete all of its posts without writing an explicit event handler in every affected plugin.

Remarks: The cascade runs asynchronously after the triggering event is emitted. It uses the same backing store as the entity’s configured repository — no cross-store operations are supported. For action: 'update', set must be provided; the framework will throw at startup if set is absent on an update cascade. filter uses the same filter expression syntax as list operations, supporting field equality checks and basic comparators against the entity’s stored fields.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Event emitted on the SlingshotEventBus after a route operation completes successfully.

Can be supplied as a plain string shorthand (just the event key) or as a full object when you need to control the payload fields or include framework context fields. The event is never emitted if the route handler returns an error response.

Remarks: Event keys that use a forbidden namespace (security., auth:, community:delivery., push:, app:) are rejected at validation time. payload defaults to including all entity fields when omitted — specify an explicit list to limit the data surface exposed to event consumers.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Idempotency configuration for a single entity operation.

When enabled, the framework stores the first successful JSON response under a derived server-side key and replays it on later retries that present the same Idempotency-Key header. Reusing the same key with a different request fingerprint is rejected with HTTP 409.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Route configuration for a named (non-CRUD) entity operation.

Extends RouteOperationConfig with method — an optional HTTP method override. Named operations default by operation kind:

  • lookupGET
  • existsHEAD
  • customhttp.method when declared on the operation
  • everything else → POST

Source: packages/slingshot-core/src/entityRouteConfig.ts

Configuration applied to a single CRUD operation or named custom operation.

Used as the value type for the standard CRUD fields (create, get, list, update, delete) and for entries in EntityRouteConfig.operations. All fields are optional — unset fields fall through to EntityRouteConfig.defaults.

Remarks: Merge precedence: specific operation config fields override defaults fields. Use resolveOpConfig to obtain the merged result for a given operation name. middleware entries are resolved by name from the entity plugin config’s middleware registry — referencing an unknown name is a startup-time error.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Permission check applied to a route operation.

The framework’s permission evaluator checks whether the authenticated subject holds a grant for requires within the resolved scope. The check runs after the auth middleware has established the request identity and before the route handler is called.

Remarks: ownerField enables resource-ownership bypass: if the entity record’s ownerField matches the authenticated user ID, the permission check is skipped and access is granted. or provides an additive alternative action — the request is allowed if the subject holds either requires or or. scope adds extra key/value pairs to the permission scope resolution context, allowing multi-tenant checks (e.g., scoping a grant to a specific tenantId).

Source: packages/slingshot-core/src/entityRouteConfig.ts

Configuration for createRouterAdapter.

A default bus handles all events not matched by a namespace prefix. Namespace prefixes allow routing specific event families to dedicated buses (e.g., community events to a Redis-backed adapter while security events stay in-process).

Source: packages/slingshot-core/src/routerAdapter.ts

Per-route rate limit configuration applied by the framework’s rate-limit middleware.

The framework derives the rate-limit key from the authenticated user ID when auth is enabled, or from the request IP address for public routes. Counters are stored in the configured cache store and reset after each windowMs rolling window.

Remarks: Rate limits are applied per operation — set a tighter limit on create or delete while leaving list unrestricted. Both windowMs and max must be positive integers.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Data retention policy for hard-deleting soft-deleted records after a grace period.

When configured, the framework schedules a background job that periodically queries for soft-deleted records that are older than after and match the when conditions, then permanently removes them from the backing store.

Remarks: This config is only meaningful for entities that use a soft-delete pattern (i.e., records are marked deleted rather than physically removed). The after duration uses the format {positive integer}{unit} where unit is one of s (seconds), m (minutes), h (hours), d (days), w (weeks), or y (years). The when filter is evaluated against the stored entity record fields using the same filter expression syntax as list operations.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Outbound webhook configuration for a named webhook trigger.

Named webhooks are declared in EntityRouteConfig.webhooks and fired by the framework after a route operation succeeds. The webhook key corresponds to a registered webhook handler in the app’s webhook registry.

Remarks: Omitting payload sends all entity fields to the webhook target. Specify an explicit list to limit the data surface, especially for webhooks that cross trust boundaries.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Runtime-agnostic file system contract.

Used by framework utilities that write files (generated configs, SSH keys, etc.). Abstracts over Bun.write / Bun.file so code stays runtime-portable.

Source: packages/slingshot-core/src/runtime.ts

Runtime-agnostic glob file scanner. Used for auto-discovery of route files, model schemas, etc.

Source: packages/slingshot-core/src/runtime.ts

Runtime-agnostic password hashing contract.

Abstracts over Bun’s Bun.password API so that tests and alternative runtimes can substitute a faster or mock implementation without touching calling code.

Source: packages/slingshot-core/src/runtime.ts

Factory for starting an HTTP (and optionally WebSocket) server.

Abstracts over Bun’s Bun.serve() API so framework bootstrap code can remain runtime-portable and testable with mock implementations.

Source: packages/slingshot-core/src/runtime.ts

A running HTTP server instance. Returned by RuntimeServerFactory.listen().

Source: packages/slingshot-core/src/runtime.ts

Options passed to RuntimeServerFactory.listen() to start the HTTP server.

Source: packages/slingshot-core/src/runtime.ts

Runtime-agnostic SQLite database handle.

Abstracts over Bun’s Database API so that framework code can remain runtime-portable. All SQLite interactions in slingshot go through this interface.

Source: packages/slingshot-core/src/runtime.ts

A prepared SQLite statement that also returns row-change metadata.

Source: packages/slingshot-core/src/runtime.ts

Result returned by a SQLite prepared statement run() call.

Source: packages/slingshot-core/src/runtime.ts

A reusable SQLite query with typed result rows.

Source: packages/slingshot-core/src/runtime.ts

Server-side handle for an open WebSocket connection.

Source: packages/slingshot-core/src/runtime.ts

WebSocket lifecycle callbacks for the runtime server.

Matches Bun’s server-side WebSocket API shape so it can be forwarded directly.

Source: packages/slingshot-core/src/runtime.ts

Options for createSafeFetch.

The defaults reject loopback, link-local, private, and multicast IPs to provide SSRF protection. Callers may override isIpAllowed and resolveHost for custom policies or testing.

Source: packages/slingshot-core/src/http/safeFetch.ts

Per-entity search client interface resolved by the search plugin at runtime.

Wraps a provider-specific index and provides entity-level document operations. Retrieved via SearchPluginRuntime.getSearchClient(entityStorageName).

Source: packages/slingshot-core/src/searchPluginRuntime.ts

Per-field search configuration. Controls how a field participates in search operations.

Source: packages/slingshot-core/src/entityConfig.ts

Search operation — full-text or filtered search across entity records.

When useSearchProvider is true (default when the entity has a search config), the search is delegated to the configured search provider (e.g., Meilisearch). Otherwise, a DB-native LIKE/text search is used.

Source: packages/slingshot-core/src/operations.ts

Runtime interface for the slingshot-search plugin, stored in ctx.pluginState.

Consumed by the framework’s createContextStoreInfra to:

  • Register entity indexes at startup via ensureConfigEntity
  • Obtain per-entity search clients for op.search and write-through sync via getSearchClient

Source: packages/slingshot-core/src/searchPluginRuntime.ts

Minimal search provider contract for write-through document sync.

This is the minimal contract shared with slingshot-search providers. The full-featured interface (search, suggest, index management, reindex) lives in slingshot-search. Core only declares the write-side contract so the framework can sync documents without depending on the full search package.

Remarks: Kept intentionally minimal — slingshot-core stays lean for apps that don’t use search. Search plugin providers implement both this interface and the extended interface in slingshot-search.

Source: packages/slingshot-core/src/searchProvider.ts

Minimal search query shape used by op.search delegation to a search provider. Provider-specific query features (facets, geo, grouping) are passed via filter and sort.

Source: packages/slingshot-core/src/searchPluginRuntime.ts

Minimal search response shape returned by SearchClientLike.search(). Provider adapters normalise their native response to this shape.

Source: packages/slingshot-core/src/searchPluginRuntime.ts

A single secret declaration within a SecretSchema.

path is the key or parameter path used to look up the secret in the backing store. Set required: false plus a default to make the secret optional with a fallback value.

Source: packages/slingshot-core/src/secrets.ts

Read-only secret repository. Resolved at startup before any DB connections. Implementations must be self-contained (no DB dependencies).

Remarks: Providers that support batch loading (e.g., SSM GetParametersByPath) should prefetch all secrets in initialize() to avoid N+1 latency during bootstrap.

Source: packages/slingshot-core/src/secrets.ts

An active or historical session record exposed by the admin API.

Source: packages/slingshot-core/src/adminProvider.ts

Signing and crypto configuration for the Slingshot framework.

Controls HMAC signing for cookies, cursors, presigned URLs, request signing, idempotency keys, and session-binding security features.

Remarks: All features are opt-in and default to false. Enable each feature when your threat model calls for it. requestSigning and sessionBinding are strongly recommended for production APIs that accept third-party callers.

Source: packages/slingshot-core/src/signing.ts

The instance-scoped runtime state container for a Slingshot application.

Created by createApp(), attached to the Hono app instance via WeakMap, and accessible from route handlers via getContext(app).

Replaces module-level singletons with instance-scoped state. Each createApp() invocation produces its own context — no shared globals, no cross-instance leakage.

Source: packages/slingshot-core/src/context/slingshotContext.ts

The typed in-process event bus shared across all Slingshot plugins.

Each createApp() call produces its own bus instance attached to SlingshotContext.bus. Plugins subscribe and emit events through this interface without depending on a specific implementation (in-process, Redis Streams, etc.).

Remarks: Server-side policy consumers should prefer onEnvelope() so they can inspect canonical metadata such as scope and exposure without re-deriving it from payloads.

Source: packages/slingshot-core/src/eventBus.ts

Central event map for all built-in Slingshot events.

Typed key to payload pairs consumed by SlingshotEventBus. Plugin packages extend this map via TypeScript module augmentation in their own events.ts file, never by modifying this interface directly.

Source: packages/slingshot-core/src/eventMap.ts

High-level event API exposed on the Slingshot context.

Wraps an EventDefinitionRegistry and a SlingshotEventBus to provide validated, envelope-wrapped event publishing with scope projection.

Source: packages/slingshot-core/src/eventPublisher.ts

Resolved framework configuration passed to plugin lifecycle hooks.

Plugins receive this object in all four lifecycle methods (setupMiddleware, setupRoutes, setupPost, setup). It provides resolved config values and infrastructure handles needed to initialise plugin state without depending on SlingshotContext directly.

Remarks: Extracted from SlingshotContext to break the SlingshotContext ↔ SlingshotPlugin type cycle — this file has no dependency on either. Plugins should treat this object as read-only.

Source: packages/slingshot-core/src/context/frameworkConfig.ts

A transport-agnostic handler instance created by defineHandler.

The handler can be invoked directly via SlingshotHandler.invoke or mounted onto an HTTP transport by the framework’s route registration layer. The instance is deeply frozen — its configuration cannot be mutated after creation.

Source: packages/slingshot-core/src/handler.ts

Immutable package definition consumed by createApp({ packages }).

Source: packages/slingshot-core/src/packageAuthoring.ts

Non-entity route group owned by a package.

Source: packages/slingshot-core/src/packageAuthoring.ts

Minimal entity module contract shared between slingshot-core and slingshot-entity.

Source: packages/slingshot-core/src/packageAuthoring.ts

The core plugin contract for Slingshot framework plugins.

Plugins extend the framework by implementing one or more lifecycle phase methods. The framework calls each phase in a fixed order during server bootstrap, giving plugins deterministic control over when their middleware and routes are registered.

Remarks: Declare dependencies to ensure prerequisite plugins are registered first. The framework resolves dependency order before calling any plugin phases. Plugin runtime state should be published with publishPluginState(ctx.pluginState, plugin.name, state) in the earliest lifecycle phase where it becomes canonical, so it stays instance-scoped rather than module-global and dependent plugins can read it in later phases. The framework seals plugin state after bootstrap.

Source: packages/slingshot-core/src/plugin.ts

The resolved application configuration stored on SlingshotContext.

A normalised snapshot of the user-supplied app config after all defaults are applied and all referenced infrastructure handles are resolved. Accessed via ctx.config.

Remarks: Unknown types for external handles: several fields (redis, mongo, signing, captcha) are typed as unknown rather than their concrete types (ioredis Redis, Mongoose Connection, etc.) to keep slingshot-core free of hard dependencies on those packages. Cast them to the correct type at use sites in the framework layer using a JSDoc boundary comment to document the cast.

Remarks: Frozen at creation: this object is frozen by createApp() before it is stored on SlingshotContext. Mutations after creation will be silently ignored in non-strict environments and will throw in strict mode. Build new config snapshots rather than attempting to patch the existing one.

Remarks: WebSocket configuration: SlingshotResolvedConfig does not carry WebSocket state — WS runtime state is held on SlingshotContext.ws which starts as null and is populated by createServer() after the Bun server initialises. Do not access ctx.ws during plugin setup phases; it will always be null at that point.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Aggregated Slingshot runtime capabilities.

Slingshot requires a runtime that provides password hashing, SQLite, an HTTP server, filesystem access, and glob scanning. The canonical implementation is Bun; other runtimes can provide compatible shims for testing or alternative deployment targets.

Remarks: This interface is resolved from the app config at startup and injected into framework internals. Plugin code should not depend on it directly — use the higher-level APIs exposed by SlingshotContext instead.

Source: packages/slingshot-core/src/runtime.ts

Configuration for a single SSE endpoint in CreateServerConfig.sse.endpoints.

Each endpoint specifies which client-safe events it streams, an optional auth/upgrade hook, an optional per-client filter, and a heartbeat interval.

Source: packages/slingshot-core/src/sse.ts

A plugin that guarantees a setup implementation for standalone (non-framework) usage.

Use this type when a plain Hono app calls plugin.setup(app, config, bus) directly instead of going through the full framework orchestrator. Narrow SlingshotPlugin to StandalonePlugin when you need a compile-time guarantee that setup is present.

Remarks: The key guarantee: assigning a value to StandalonePlugin is a compile-time error if setup is missing or optional. This prevents a runtime crash when calling plugin.setup(...) in a plain Hono context where the framework lifecycle is absent.

Remarks: A StandalonePlugin can still implement setupMiddleware, setupRoutes, and setupPost — those fields are inherited from SlingshotPlugin. If the plugin is later registered with a full Slingshot app, the framework will call the phase methods and never call setup. Both paths can coexist without double-execution risk.

Source: packages/slingshot-core/src/plugin.ts

Pluggable object storage adapter for the upload middleware.

Implement this interface to connect any storage backend (S3, R2, local disk, etc.) to the Slingshot upload infrastructure. Registered via the uploads plugin configuration.

Source: packages/slingshot-core/src/storageAdapter.ts

A single WebSocket message that has been persisted to the backing store. Includes a unique ID and a creation timestamp for history and cursor pagination.

Source: packages/slingshot-core/src/wsMessages.ts

Infrastructure accessor bundle passed to every repository factory at startup.

StoreInfra provides lazy accessor functions for each backing store so that a repository factory can reach the correct client without depending on the concrete initialisation path. The framework constructs a single StoreInfra per app instance and passes it to every factory invocation via resolveRepo or resolveRepoAsync.

Remarks: All accessor methods throw if the corresponding store is not configured for this app instance. Always call only the accessor that matches the active StoreType — never call infra.getRedis() inside a Postgres factory, for example. Do not call any accessor at module load time. Accessors are safe to call only from inside a repository factory function, after the framework bootstrap has completed. appName is available for namespacing store keys, table prefixes, or index names.

Source: packages/slingshot-core/src/storeInfra.ts

A reference to the subject of a permission grant (who the grant applies to).

Source: packages/slingshot-core/src/permissions.ts

Options for SlingshotEventBus.on() subscriptions.

Remarks: The InProcessAdapter does not support durable subscriptions — registering one logs a warning and degrades to a normal (non-durable) subscription. Durable support requires a queue-backed adapter (e.g., Redis Streams or BullMQ).

Source: packages/slingshot-core/src/eventBus.ts

Input for suspending a user account via the admin API.

Source: packages/slingshot-core/src/adminProvider.ts

User suspension adapter methods — required unless auth.checkSuspensionOnIdentify is explicitly disabled, or when admin.api is configured.

Suspension prevents a user from authenticating without deleting their account. The auth plugin checks suspension status during identify by default and on refresh before minting fresh credentials.

Source: packages/slingshot-core/src/auth-adapter.ts

Structured event data for system messages. Stored in the systemEvent field when type is 'system'.

System messages are generated by the server, not authored by users. The body field contains a human-readable fallback string.

Source: packages/slingshot-core/src/content.ts

Declarative tenant-isolation contract for one named application boundary.

Source: packages/slingshot-core/src/tenantBoundaries.ts

Instance-scoped registrar used to inventory and finalize tenant boundaries.

Source: packages/slingshot-core/src/tenantBoundaries.ts

Multi-tenant scoping configuration for an entity.

When set, the framework ensures that all queries are automatically scoped to the current tenant context. The field must exist in EntityConfig.fields and should be of type 'string'.

Source: packages/slingshot-core/src/entityConfig.ts

Request or worker identity fields accepted when capturing a tenant snapshot.

Source: packages/slingshot-core/src/context/tenantExecutionContext.ts

Immutable, versioned tenant identity envelope safe for asynchronous transport.

Source: packages/slingshot-core/src/context/tenantExecutionContext.ts

Options for restricting an operation to a specific tenant. Passed to GroupsAdapter methods that need to scope results by tenant.

Source: packages/slingshot-core/src/auth-adapter.ts

A PermissionsAdapter that adds a clear() method for test isolation. Implement this interface in test-only adapters to reset state between test cases.

Source: packages/slingshot-core/src/permissions.ts

Aggregated timing entry in a MetricsSnapshot.

Source: packages/slingshot-core/src/metrics.ts

Narrow seam implemented by the transactional-events package.

Source: packages/slingshot-core/src/eventPublisher.ts

Context supplied to one transactionally deduplicated event handler.

Source: packages/slingshot-core/src/eventPublisher.ts

Durable named-consumer options for SQL inbox deduplication.

Source: packages/slingshot-core/src/eventPublisher.ts

Narrow synchronous seam used to enqueue an outbox insert on an open transaction scope.

Source: packages/slingshot-core/src/eventPublisher.ts

Invoke one configured native array-pull operation.

Source: packages/slingshot-core/src/operations.ts

Invoke one configured native array-push operation.

Source: packages/slingshot-core/src/operations.ts

Invoke one configured native batch operation.

Source: packages/slingshot-core/src/operations.ts

Insert one entity.

Source: packages/slingshot-core/src/operations.ts

Idempotently delete the entity selected by match.

Source: packages/slingshot-core/src/operations.ts

Internal scope-aware entity lookup passed through the StoreInfra DI boundary.

Source: packages/slingshot-core/src/storeInfra.ts

Immutable metadata needed to rebuild one entity adapter inside a transaction.

Source: packages/slingshot-core/src/storeInfra.ts

Bind an entity resolution to one open transaction scope.

Source: packages/slingshot-core/src/transactions.ts

Invoke one configured native field-update operation.

Source: packages/slingshot-core/src/operations.ts

Invoke one configured native increment operation.

Source: packages/slingshot-core/src/operations.ts

Read at most one entity for later result:N.path bindings.

Source: packages/slingshot-core/src/operations.ts

Framework-owned entry point for imperative package/domain transactions.

Source: packages/slingshot-core/src/transactions.ts

Transaction operation — execute multiple entity operations atomically.

Steps run in order; the whole transaction rolls back on failure when the backend provides a real transaction wrapper.

This is the explicit composition boundary for callers who want several operations to behave as one unit. Standard entity operations should remain safe-by-default without requiring consumers to manage transaction strategy.

Source: packages/slingshot-core/src/operations.ts

One sanitized framework-owned effect that failed after database commit.

Source: packages/slingshot-core/src/transactions.ts

Opaque identity for one framework-owned transaction.

A scope contains no database driver. Obtain it only from TransactionManager.run and pass it back through scope-aware framework APIs.

Source: packages/slingshot-core/src/transactions.ts

Invoke one configured native transition operation.

Source: packages/slingshot-core/src/operations.ts

Update the single entity selected by match.

Source: packages/slingshot-core/src/operations.ts

Transition operation — atomically move a record from one state to another.

The operation matches a record by match fields, verifies the current value of field equals from, then updates it to to. Optional set fields are updated at the same time. Useful for state machine transitions (e.g., pendingactive).

Source: packages/slingshot-core/src/operations.ts

Cloud-agnostic trigger adapter.

Source: packages/slingshot-core/src/functions.ts

Metadata extracted from a trigger event by a TriggerAdapter.

Extends Partial<HandlerMeta> with raw identity fields that the Lambda runtime hands to the configured IdentityResolver to construct the canonical Actor. Trigger adapters can either set the actor field directly or supply the raw identity fields and let buildMeta derive the actor through the resolver.

Field names mirror IdentityResolverInput.

Source: packages/slingshot-core/src/functions.ts

Per-trigger wrapping options, such as enabling or configuring IdempotencyOpts.

Source: packages/slingshot-core/src/functions.ts

One normalized record extracted from a trigger event.

Source: packages/slingshot-core/src/functions.ts

Common request context shared by package-authored domain route handlers.

Source: packages/slingshot-core/src/packageAuthoring.ts

Request validation contract for package-authored domain routes.

Source: packages/slingshot-core/src/packageAuthoring.ts

Minimal responder helpers available inside package-authored route handlers.

Source: packages/slingshot-core/src/packageAuthoring.ts

OpenAPI-oriented response metadata for package-authored domain routes.

Source: packages/slingshot-core/src/packageAuthoring.ts

Inferred typed request values exposed to a domain route handler.

Source: packages/slingshot-core/src/packageAuthoring.ts

Input for unsuspending (reinstating) a user account via the admin API.

Source: packages/slingshot-core/src/adminProvider.ts

Input for updating a user’s profile fields via the admin API.

Source: packages/slingshot-core/src/adminProvider.ts

Metadata record stored when a file is uploaded via the framework upload middleware.

Used to verify ownership and tenancy when users request presigned download URLs or initiate delete operations. Stored in the UploadRegistryRepository.

Source: packages/slingshot-core/src/uploadRegistry.ts

Storage contract for tracking upload ownership and metadata.

Implementations store UploadRecord entries keyed by the storage key. The upload middleware calls register() after a successful upload. Presigned-download and delete handlers call get() to verify ownership.

Source: packages/slingshot-core/src/uploadRegistry.ts

Metadata about a completed upload, populated by the upload middleware and stored in c.get('uploadResults') for route handlers to inspect.

Source: packages/slingshot-core/src/storageAdapter.ts

Upload plugin runtime state stored on the context.

Populated by the uploads plugin during setupPost. adapter is the resolved StorageAdapter instance; config is the frozen uploads plugin configuration.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Upsert operation — create or update a record based on uniqueness fields.

Matches on the fields listed in match. If a record exists, updates the set fields. If not, creates a new record applying onCreate defaults.

Source: packages/slingshot-core/src/operations.ts

Filter options for listing users via EnterpriseAdapter.listUsers(). All fields are optional and combined with AND semantics — only records matching every provided filter are returned.

Source: packages/slingshot-core/src/auth-adapter.ts

A user record as read from the auth store.

Returned by CoreAuthAdapter.getUser(). All fields except id and suspended are optional because not all adapters populate every field.

Source: packages/slingshot-core/src/auth-adapter.ts

A single field-level validation error detail produced by the default formatter.

Source: packages/slingshot-core/src/context.ts

Extended metadata for audio/voice message attachments. Included in AssetRef when the attachment is a voice message.

Source: packages/slingshot-core/src/content.ts

WebAuthn adapter methods — required when auth.mfa.webauthn is configured.

Manages passkey credentials for users. Called during the WebAuthn registration and authentication ceremonies. The signCount must be updated on every successful authentication to guard against cloned authenticators.

Source: packages/slingshot-core/src/auth-adapter.ts

A registered WebAuthn credential (passkey) for a user.

Created during the WebAuthn registration ceremony and verified on each authentication attempt. The signCount is incremented on every use to detect cloned authenticators.

Source: packages/slingshot-core/src/auth-adapter.ts

Options controlling withIdempotency behaviour.

Source: packages/slingshot-core/src/idempotency/index.ts

Default persistence settings applied to rooms that don’t specify their own config.

Source: packages/slingshot-core/src/wsMessages.ts

Storage contract for WebSocket message persistence.

Implementations store messages per (endpoint, room) scope with configurable max count and TTL-based expiration. Used by the framework’s WS history and session-recovery features.

Source: packages/slingshot-core/src/wsMessages.ts

Minimal WS endpoint shape that plugins register during setupPost.

Plugins write onRoomSubscribe and incoming into SlingshotContext.wsEndpoints[endpointName]. The framework’s WS message handler reads these fields at connection time, so mutations made during setupPost are visible before any client connects.

Remarks: incoming entries are merged with any static handlers already present in the endpoint config. Plugin-registered handlers take precedence on key collision.

Source: packages/slingshot-core/src/wsHelpers.ts

Rolling-window message rate limit bucket for a single WebSocket connection.

Tracks the count of messages received in the current window. When count exceeds the configured maxMessages, the connection is throttled (dropped or closed).

Source: packages/slingshot-core/src/context/slingshotContext.ts

Per-connection WebSocket message rate limit configuration. Consumed by the framework to enforce a rolling message window per socket.

Source: packages/slingshot-core/src/context/slingshotContext.ts

WebSocket connection state recovery configuration. When set on an endpoint, sessions are held after disconnect so the client can reconnect and resume within the configured window.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Disconnected WebSocket session entry held for the recovery window.

When a client disconnects unexpectedly, the session is retained in WsState.sessionRegistry until expiresAt so the client can reconnect and resume from lastEventId without missing messages.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Instance-scoped WebSocket runtime state container.

Populated by createServer() after the Bun server is started. null on the context when the application has no WebSocket endpoints configured.

Remarks: The socket registry uses unknown types to prevent slingshot-core from importing Bun types. Cast to ServerWebSocket<SocketData> at use sites in the framework layer.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Cross-instance WebSocket transport adapter.

Used by the framework to fan out WS messages across multiple server instances in a distributed deployment (e.g., via Redis Pub/Sub). A null handle means single-instance deployment with no cross-instance delivery.

Remarks: Defined here (not in framework internals) so SlingshotContext can reference it without a circular dependency on the framework’s transport layer.

Source: packages/slingshot-core/src/context/slingshotContext.ts

Discriminator for the kind of actor making a request.

  • 'user' — an interactive human user session.
  • 'service-account' — a machine-to-machine client (e.g. M2M JWT with azp/client_id).
  • 'api-key' — a statically configured bearer/API-key client.
  • 'system' — an internal framework-initiated action (cron, lifecycle).
  • 'display' — a read-only “screen” bound to ONE resource (e.g. a game cast to a TV). Carries id: null on purpose, so it can never satisfy userAuth (which requires kind === 'user' AND a non-null id) and can never widen into a user session. Everything a display may see is granted explicitly by the package that minted its token.
  • 'anonymous' — unauthenticated request.

Source: packages/slingshot-core/src/identity.ts

A transport-agnostic post-handle side effect.

After hooks run sequentially once the handler returns a validated output. They receive the same HandlerArgs plus the handler’s output. Failures in after hooks are logged but do not prevent the response from being returned to the caller.

Source: packages/slingshot-core/src/handler.ts

Resolved method for an AggregateOpConfig.

Computes a scalar value (count, sum, min, max, avg) over a filtered set of entities. The return type is unknown at the type level because the aggregate kind and field type determine the actual shape at runtime.

Source: packages/slingshot-core/src/operations.ts

The Hono Env type for all Slingshot routers.

Pass this as the generic parameter to Hono, OpenAPIHono, and Context to get fully-typed access to request variables set by the framework middleware.

Source: packages/slingshot-core/src/context.ts

The Hono context variable bag set by framework middleware on every request.

These variables are accessible via c.get('variableName') in route handlers. They are populated by the framework before any plugin or user route runs.

Source: packages/slingshot-core/src/context.ts

Resolved method for an ArrayPullOpConfig.

Removes a value from an array field on an existing entity. Returns the full updated entity.

Source: packages/slingshot-core/src/operations.ts

Resolved method for an ArrayPushOpConfig.

Appends a value to an array field on an existing entity. Returns the full updated entity.

Source: packages/slingshot-core/src/operations.ts

Resolved method for an ArraySetOpConfig.

Replaces the entire array field on an existing entity with the provided array. With dedupe: true (the default), the value is deduplicated server-side before writing — equivalent to [...new Set(newArray)].

Source: packages/slingshot-core/src/operations.ts

The complete auth adapter type — the union of all tier interfaces.

CoreAuthAdapter is always required. All other tiers are Partial because a given deployment may not need OAuth, MFA, WebAuthn, roles, groups, suspension, or enterprise features. The auth plugin validates that the required tier methods are present based on the configured features at startup.

Source: packages/slingshot-core/src/auth-adapter.ts

Auto-default sentinel values for field creation.

  • 'uuid' — generates a UUID v4 string
  • 'now' — sets the field to the current timestamp at creation (or update when combined with onUpdate)
  • 'cuid' — generates a CUID string (shorter and URL-safe alternative to UUID)

Source: packages/slingshot-core/src/entityConfig.ts

Resolved method for a BatchOpConfig.

Applies a bulk write (update or delete) to all entities matching the filter. Returns the number of affected records.

Source: packages/slingshot-core/src/operations.ts

Unified cache interface: implementations wrap a backing store (Redis, memory, SQLite, …) behind a consistent get/set/del API used by response caching and session storage.

Source: packages/slingshot-core/src/cache.ts

Identifier for a named cache store (redis | mongo | sqlite | memory | postgres).

Source: packages/slingshot-core/src/cache.ts

Supported CAPTCHA verification providers.

  • 'recaptcha' — Google reCAPTCHA v2 or v3
  • 'hcaptcha' — hCaptcha
  • 'turnstile' — Cloudflare Turnstile

Source: packages/slingshot-core/src/captcha.ts

Authentication strategy enforced at WebSocket channel subscribe time.

  • 'userAuth' — requires a valid session (resolved by RequestActorResolver)
  • 'bearer' — requires a valid bearer token
  • 'none' — no auth check; any client may subscribe

Remarks: This mirrors RouteAuthConfig from entityRouteConfig.ts but applies to the WebSocket subscribe handshake rather than HTTP route handlers. The auth check runs once when the client sends the initial subscribe message; it is not re-evaluated on every incoming WebSocket frame.

Source: packages/slingshot-core/src/entityChannelConfig.ts

Resolved method for a CollectionOpConfig.

Manages an embedded sub-document array on a parent entity. Exposes five sub-operations as properties on a single object.

Source: packages/slingshot-core/src/operations.ts

Valid operations on a collection (embedded array of sub-documents).

Source: packages/slingshot-core/src/operations.ts

Resolved method for a ComputedAggregateOpConfig.

Reads a set of entities, runs user-supplied compute functions over them, and writes the results back. Returns void — side-effects only.

Source: packages/slingshot-core/src/operations.ts

Aggregate computation function names used in op.aggregate and op.computedAggregate.

  • 'count' — number of records in the group (always an integer)
  • 'sum' — numeric sum of a specified field across the group
  • 'avg' — arithmetic mean of a specified field across the group
  • 'min' — smallest value of a specified field in the group
  • 'max' — largest value of a specified field in the group

Source: packages/slingshot-core/src/operations.ts

Source for a config definition’s values.

Source: packages/slingshot-core/src/config.ts

Resolved method for a ConsumeOpConfig with returns: 'boolean'.

Atomically finds an entity matching the filter and deletes it in a single operation. Returns true if an entity was found and consumed, false if none matched.

Source: packages/slingshot-core/src/operations.ts

Resolved method for a ConsumeOpConfig without returns: 'boolean'.

Atomically finds an entity matching the filter, deletes it, and returns it. Returns null if no entity matched.

Source: packages/slingshot-core/src/operations.ts

Content format indicator. Tells the client how to parse the body field.

  • 'plain' — render as literal text, no markdown parsing, tokens still parsed
  • 'markdown' — parse as GitHub-flavored markdown, then parse tokens in text runs

Source: packages/slingshot-core/src/content.ts

A single segment of parsed content body. Discriminated by type.

Source: packages/slingshot-core/src/content.ts

Input contract for Matches.definePackage(...). The contract supplies the package name and accepts contract objects in dependencies; everything else mirrors the module-level DefinePackageInput.

Source: packages/slingshot-core/src/packageAuthoring.ts

Mutable bootstrap registrar that collects auth-boundary dependencies (route auth, cache adapters, email templates, …) from plugins, then drains them into a frozen CoreRegistrarSnapshot.

Source: packages/slingshot-core/src/coreRegistrar.ts

A frozen snapshot of all auth-boundary dependencies collected by CoreRegistrar, produced after the plugin lifecycle completes.

Source: packages/slingshot-core/src/coreRegistrar.ts

Custom auto-default resolver function for entity field defaults.

Extends the built-in 'uuid' | 'cuid' | 'now' auto-default sentinels with consumer-defined strategies. Called during record creation when a field’s default value is a string that does not match a built-in sentinel.

Return the generated value to use it, or undefined to signal that the sentinel is not recognized (which will throw an error).

Source: packages/slingshot-core/src/entityConfig.ts

Custom on-update resolver function for entity field update-time values.

Extends the built-in 'now' on-update sentinel with consumer-defined strategies. Called during record updates when a field’s onUpdate value is a string that does not match 'now'.

Return the computed value to apply it, or undefined to skip the field.

Source: packages/slingshot-core/src/entityConfig.ts

Supported truncation levels for date-based groupBy.

Source: packages/slingshot-core/src/operations.ts

Resolved method for a DeriveOpConfig.

Queries one or more source entities and merges their fields into a new virtual object according to the configured merge strategy. Useful for aggregating data from multiple related entities without creating a permanent denormalized record.

Source: packages/slingshot-core/src/operations.ts

A static email template (subject/html/text) registered by a plugin and consumed by the mail plugin.

Source: packages/slingshot-core/src/emailTemplates.ts

Stable semantic capability identifiers for standard entity adapters.

Operation availability and concurrency guarantees are separate on purpose: an adapter may expose an operation executor without being able to provide an atomic implementation of that operation.

Source: packages/slingshot-core/src/entityCapabilities.ts

A backend’s explicit support status for one semantic capability.

Source: packages/slingshot-core/src/entityCapabilities.ts

The input type accepted by entityChannelConfigSchema.

Equivalent to EntityChannelConfig from entityChannelConfig.ts but reflects Zod’s input-side coercions (i.e., what you pass in before parsing). Use this type when working with raw or partially-typed config objects that will be validated before use — for example, configs read from JSON files or passed across module boundaries without prior validation.

Remarks: In practice EntityChannelConfigInput and EntityChannelConfig are structurally identical because the schema contains no transformations. Prefer importing EntityChannelConfig directly when your config object is already validated.

Source: packages/slingshot-core/src/entityChannelConfigSchema.ts

CRUD operations that a EntityRouteDataScopeConfig entry can target.

Remarks: Omit EntityRouteDataScopeConfig.applyTo to apply an entry to all five CRUD routes. Named operations are not part of this union and are never subject to dataScope.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Single DTO mapper function — receives a storage record and returns the API shape for it. The framework applies the selected mapper to single records, arrays, and the items of paginated responses automatically.

createDtoMapper(...) from @lastshotlabs/slingshot produces a function that fits this contract.

Source: packages/slingshot-core/src/entityConfig.ts

Every declarative entity operation discriminant.

Source: packages/slingshot-core/src/entityCapabilities.ts

The input type accepted by entityRouteConfigSchema.

Equivalent to EntityRouteConfig from entityRouteConfig.ts but reflects Zod’s input-side coercions (i.e., what you pass in before parsing). Use this type when working with raw or partially-typed config objects that will be validated before use — for example, configs read from JSON files or constructed dynamically.

Remarks: In practice EntityRouteConfigInput and EntityRouteConfig are structurally identical because the schema contains no transformations. Prefer importing EntityRouteConfig directly when your config object is already validated.

Source: packages/slingshot-core/src/entityRouteConfigSchema.ts

Source prefix for an EntityRouteDataScopeConfig.from binding.

  • 'ctx:' reads from request context. 'ctx:actor.id' (and other ctx:actor.* paths) read the resolved actor; 'ctx:tenantId' reads the request-scoped tenant set by tenant middleware. Custom keys fall through to whatever app-defined Hono context var was set (e.g. 'ctx:inviteExpiresAt').
  • 'param:' reads from a URL path parameter (for example, 'param:orgId' reads c.req.param('orgId')).

body: and record: prefixes are intentionally not supported because scope sources must be server-side values, not client-supplied payload data or self-referential record values.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Internal resolved shape of the generated version field.

Source: packages/slingshot-core/src/entityConfig.ts

Classifies where in the invocation pipeline an error originated (validation, handler, timeout, infrastructure, etc.).

Source: packages/slingshot-core/src/functions.ts

Declares the delivery surfaces an event is allowed to reach, from internal-only to client and webhook exposure.

Source: packages/slingshot-core/src/eventTypes.ts

Union of all registered event names — the string keys of the SlingshotEventMap.

Source: packages/slingshot-core/src/eventTypes.ts

Result of validating an event payload against a registered schema.

Source: packages/slingshot-core/src/eventSchemaRegistry.ts

Resolved method for an ExistsOpConfig.

Efficiently checks whether at least one entity matches the filter — does not load the full record. Use instead of a lookup when you only need a boolean (e.g. uniqueness checks, pre-condition guards).

Source: packages/slingshot-core/src/operations.ts

All supported field type tokens for use with field.*() builders.

Each token maps to a TypeScript type via FieldTypeMap and controls how adapters store and serialise field values for each backing store.

Source: packages/slingshot-core/src/entityConfig.ts

Resolved method for a FieldUpdateOpConfig.

Applies a partial update to an existing entity. The params object supplies filter values (which entity to update), while input supplies the new field values. The full updated entity is returned.

Source: packages/slingshot-core/src/operations.ts

A composable filter expression for entity queries.

Top-level fields are field-level equality/operator checks. $and and $or allow logical composition of sub-expressions.

Remarks: Evaluation order: top-level field conditions are combined with an implicit AND. $and further ANDs an array of sub-expressions; $or ORs them. When both $and and $or are present on the same level they are themselves combined with AND (i.e. all $and clauses AND the $or clause must hold). Sub-expressions inside $and/$or are themselves full FilterExpression objects and may nest further $and/$or arrays.

Source: packages/slingshot-core/src/operations.ts

Union of all supported comparison operator objects for a single field filter.

Source: packages/slingshot-core/src/operations.ts

A single field’s filter value — a literal, null, or a comparison operator.

String values starting with 'param:' are treated as parameter references resolved at runtime (e.g. 'param:userId' resolves to the userId param). The sentinel 'now' in comparison operators resolves to new Date().

Remarks: The 'param:x' prefix is a runtime injection mechanism: the executor reads the call-time params map and substitutes the value of key x before the filter reaches the database adapter. This means filters can be defined statically in the operation config while still accepting dynamic values per call. Literal strings that do not start with 'param:' are passed through unchanged as constant equality checks.

Source: packages/slingshot-core/src/operations.ts

Builds a short fingerprint hash from stable HTTP request headers, used for unauthenticated bot detection and request fingerprinting.

Source: packages/slingshot-core/src/rateLimit.ts

Whether the grant allows or denies the specified roles on a resource.

Remarks: Deny wins: when the evaluator collects effective grants for a subject (including group-expanded grants), any 'deny' grant that covers the requested action causes can() to return false — regardless of how many 'allow' grants also apply. This holds across all cascade levels: a specific-resource deny overrides a global allow, and a global deny overrides a specific-resource allow.

Source: packages/slingshot-core/src/permissions.ts

A transport-agnostic pre-handle check.

Guards run sequentially before the handler. A guard that throws prevents subsequent guards and the handler from executing. Throw HandlerError to signal a structured failure, or any Error for unexpected conditions.

Return void (or a resolved promise) to allow the pipeline to continue.

Source: packages/slingshot-core/src/handler.ts

Severity of a failed health indicator.

  • critical — a failure flips /health/ready to 503 (the load balancer should pull the instance out of rotation).
  • warning — a failure marks the response 'degraded' but keeps the 200 status, so the instance stays in rotation while operators investigate.

Source: packages/slingshot-core/src/observability/health.ts

Coarse health categorisation reported by a component.

  • healthy — fully operational.
  • degraded — operating with reduced capability (e.g. fallback adapter, elevated lag, partial connectivity). Traffic may continue.
  • unhealthy — not serving its contract; callers should fail over or fail fast.

Source: packages/slingshot-core/src/observability/health.ts

Branded string used to keep idempotency keys distinct from arbitrary strings.

Source: packages/slingshot-core/src/idempotency/index.ts

Resolved type for op.increment — atomically adds by (default 1) to a numeric field and returns the updated entity. Pass a negative by to decrement.

Source: packages/slingshot-core/src/operations.ts

Infer the CreateInput type from a fields record.

Excludes auto-managed fields (auto-generated defaults and onUpdate fields); fields with a default or marked optional become optional, while the rest are required.

Source: packages/slingshot-core/src/entityConfig.ts

Infer the full entity type (all fields, respecting optional).

Source: packages/slingshot-core/src/entityConfig.ts

Resolve the TypeScript type for a single field, using the literal enum union when the field carries narrowed EnumValues, falling back to string otherwise.

Source: packages/slingshot-core/src/entityConfig.ts

Infer the full set of operation methods for a record of operation configs.

type Ops = InferOperationMethods<typeof myOps, MyEntity>;
// { getByRoom: (params) => Promise<PaginatedResult<MyEntity>>; ... }

Source: packages/slingshot-core/src/operations.ts

Infers an entity’s update-input shape from its field definitions — mutable fields only, each optional, and nullable when the field itself is optional.

Source: packages/slingshot-core/src/entityConfig.ts

Severity ordering used by createConsoleLogger for level filtering.

Source: packages/slingshot-core/src/observability/logger.ts

Resolved method for a LookupOpConfig without returns: 'one'.

Returns a cursor-paginated list of entities matching the filter params. The result always includes items, total, and an optional nextCursor.

Source: packages/slingshot-core/src/operations.ts

Public package name represented in generated maturity metadata.

Source: packages/slingshot-core/src/generated/packageMaturity.ts

Strategy for merging results from multiple sources in op.derive.

  • 'union' — deduplicate by ID across all sources
  • 'concat' — concatenate all results in source order
  • 'intersect' — return only IDs present in all sources
  • 'first' — return results from the first non-empty source only
  • 'priority' — like first, but sources are weighted by configuration

Source: packages/slingshot-core/src/operations.ts

HTTP methods available as overrides for named (non-CRUD) entity operations.

CRUD operations (create, list, get, update, delete) ignore this — their HTTP methods are semantically fixed by the operation type.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Notification priority persisted by the notifications plugin.

Source: packages/slingshot-core/src/notificationsPeer.ts

Union of all supported declarative operation configuration types. Used as the value type in ResolvedOperations.operations and PipeStep.config.

Source: packages/slingshot-core/src/operations.ts

Maturity label for a Slingshot package, driving the runtime warning emitted for non-stable packages.

Source: packages/slingshot-core/src/stability.ts

Resolved method for a PipeOpConfig.

Executes a sequence of operations in order, threading the output of each step as input to the next. The final step’s output is returned.

Source: packages/slingshot-core/src/operations.ts

Instance-scoped map of plugin name -> plugin-owned state.

Each plugin stores its runtime state under its own plugin name key. Values are opaque to the framework; plugins own their state shape and expose typed accessors for dependent plugins.

Source: packages/slingshot-core/src/pluginStateTypes.ts

The operation a policy resolver is being asked to authorize.

Discriminated union — the kind field tells the resolver what to expect in the other PolicyInput fields:

  • 'create'input is the create payload; record is null.
  • 'list'record and input are both null. Resolvers on list operations gate whether the list route is callable at all; per-row filtering uses dataScope or a named op with explicit filter logic.
  • 'get'record is the fetched row; input is null.
  • 'update'record is the fetched row; input is the update payload. Policy runs AFTER dataScope has matched.
  • 'delete'record is the fetched row; input is null.
  • 'operation' — named-op route. name is the operation key declared in EntityRouteConfig.operations. record may be null if the named op does not pre-fetch a record before invoking policy.

Source: packages/slingshot-core/src/entityRouteConfig.ts

The resolver signature. Registered by consumer packages at setupMiddleware and looked up by name at request time.

Resolvers must be pure in the HTTP sense: they may read from databases, caches, or other services, but they must NOT write to the response, throw to terminate the request (return false or { allow: false } instead), or mutate the request.

Source: packages/slingshot-core/src/entityRouteConfig.ts

A guard that runs after authentication, in registration order; the first to return a PostAuthGuardFailure short-circuits the request.

Source: packages/slingshot-core/src/routeAuth.ts

Result returned by a post-auth guard when the request should be rejected.

Source: packages/slingshot-core/src/routeAuth.ts

Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.

Source: packages/slingshot-core/src/postgresRuntime.ts

Exposure mode declared by a package contract for a public entity ref.

Source: packages/slingshot-core/src/packageAuthoring.ts

Converts a notification record into a PushMessageLike, optionally merging caller-supplied defaults.

Source: packages/slingshot-core/src/pushPeer.ts

Rate-limit backend that tracks attempt counts within a rolling window; returns true when the limit is exceeded (caller responds 429).

Source: packages/slingshot-core/src/rateLimit.ts

A record of repository factories keyed by StoreType.

Every key (redis, mongo, sqlite, memory, postgres) must be present. At runtime, only the factory matching the configured store type is called. The others are never invoked and may throw if their infra is unavailable.

Source: packages/slingshot-core/src/storeInfra.ts

Resolves the connecting actor for framework WebSocket/SSE upgrades without depending on the auth plugin; registered by the auth plugin during setup.

Source: packages/slingshot-core/src/requestActorResolver.ts

Fields exposed by a resolved config after optional concurrency-field injection.

Source: packages/slingshot-core/src/entityConfig.ts

The typed result of resolving a SecretSchema against a SecretRepository.

Required secrets (required is true or omitted) produce string values. Optional secrets (required: false) produce string | undefined. The resolved object is Readonly and frozen — never mutate it.

Source: packages/slingshot-core/src/secrets.ts

Authentication strategy for a route or operation.

  • 'userAuth' — requires a valid session cookie or user token (via RouteAuthRegistry.userAuth)
  • 'bearer' — requires a bearer token (via RouteAuthRegistry.bearerAuth)
  • 'none' — publicly accessible; no auth middleware applied

Remarks: Set on EntityRouteConfig.defaults to apply the same auth strategy to all generated CRUD routes, then override individual operations (e.g. list: { auth: 'none' }) as needed. The framework wires the corresponding middleware from RouteAuthRegistry automatically — you never call the middleware factory directly.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Auth middleware registry the auth plugin provides to the framework so framework-owned routes can apply auth and role guards without depending on the auth plugin.

Source: packages/slingshot-core/src/routeAuth.ts

Scope used when deriving the server-side storage key for entity route idempotency.

The final key always includes the entity name, operation name, and client-supplied Idempotency-Key. scope controls which request identity dimension is added on top.

Source: packages/slingshot-core/src/entityRouteConfig.ts

A branded route key string in the format "METHOD /path" (method always uppercased).

Constructed exclusively via routeKey() — never hand-typed — to prevent drift between the route constant definition and the shouldMountRoute runtime check.

Source: packages/slingshot-core/src/routeOverrides.ts

Named middleware factory registry for an entity’s routes.

Declares which middleware factories are available for this entity’s operations. Keys are the middleware names referenced in RouteOperationConfig.middleware and EntityChannelDeclaration.middleware. Values are always true — the actual factory functions are resolved from the entity plugin config’s middleware map at startup, not stored here.

Remarks: This interface serves as a declaration manifest: it tells the framework (and TypeScript) which middleware names are valid for this entity. The concrete factory implementations live in the plugin config, keeping config serializable and free of function references. Referencing a name in RouteOperationConfig.middleware that is absent from this registry is a startup-time error.

Source: packages/slingshot-core/src/entityRouteConfig.ts

Resolved method for a SearchOpConfig without paginate: true.

Performs a full-text search and returns a flat array of matching entities.

Source: packages/slingshot-core/src/operations.ts

Resolved method for a SearchOpConfig with paginate: true.

Performs a full-text search against the configured search provider and returns a cursor-paginated result. Requires a search plugin to be configured.

Source: packages/slingshot-core/src/operations.ts

A record of named secret declarations, keyed by the property name that will appear on the resolved secrets object.

Source: packages/slingshot-core/src/secrets.ts

The backing store type for secret resolution.

  • 'env' — reads from process environment variables (always available, zero config)
  • 'ssm' — reads from AWS SSM Parameter Store (production, supports rotation)
  • 'file' — reads from a local file (e.g. a .env.secrets file)

Source: packages/slingshot-core/src/secrets.ts

Extracts the subset of SlingshotEventMap keys that belong to the security.* namespace.

Source: packages/slingshot-core/src/eventMap.ts

Any module that can be owned by a package definition.

Source: packages/slingshot-core/src/packageAuthoring.ts

Soft-delete configuration for an entity.

When set, delete operations update a field instead of removing the record. Two strategies are supported:

  • { field, value } — sets the field to a specific value (e.g., status: 'deleted')
  • { field, strategy: 'non-null' } — sets a nullable field to a non-null timestamp

Soft-deleted records are excluded from list and getById queries by default.

Source: packages/slingshot-core/src/entityConfig.ts

Data attached to each active SSE connection.

The generic parameter T allows endpoint-specific metadata to be added at upgrade time (e.g., subscription filters). The base fields (id, actor, requestTenantId, endpoint) are always present.

Source: packages/slingshot-core/src/sse.ts

Per-client, per-event filter for SSE fanout.

Called for each (client, event) pair before delivering a message. Return false to suppress delivery to a specific client (e.g., to implement per-user or per-room filtering). Async filters are awaited — keep them fast to avoid fanout latency.

Source: packages/slingshot-core/src/sse.ts

Canonical backing store type union shared across all slingshot packages.

Used as the key type in RepoFactories<T> and CacheStoreName so that a single source-of-truth controls which stores are supported. Adding a new store here propagates to auth adapters, framework persistence, and cache adapters automatically.

Remarks: 'memory' is always available without external dependencies, making it the default for development, testing, and single-process deployments.

Source: packages/slingshot-core/src/storeType.ts

The type of entity a permission grant applies to.

  • 'user' — a concrete end-user identity; subjectId is the user’s primary key as stored in the auth adapter (e.g. a UUID or nanoid)
  • 'group' — a named collection of users resolved at evaluation time via GroupResolver; subjectId is the group’s ID; grants to a group apply to all current members
  • 'service-account' — a non-human M2M client or API service identity; subjectId is the service account’s client ID or name; used for backend-to-backend trust grants that should not be confused with end-user permissions

Source: packages/slingshot-core/src/permissions.ts

First-party transport and persistence surfaces that must preserve tenant identity.

Source: packages/slingshot-core/src/tenantBoundaries.ts

Like RepoFactories``<T> but the memory factory accepts an optional infra argument, enabling direct .memory() calls in unit tests without constructing a real StoreInfra instance.

Remarks: TestableRepoFactories<T> is structurally assignable to RepoFactories<T> because a function that accepts an optional parameter also satisfies a type that requires it. This means you can pass a TestableRepoFactories<T> directly to resolveRepo without a cast. In test code, call .memory() with no arguments to get a fresh in-memory instance. Each call returns an independent instance — no shared state between calls.

Source: packages/slingshot-core/src/storeInfra.ts

Idempotent subscription cleanup function.

Source: packages/slingshot-core/src/eventPublisher.ts

Call-time literal or param:/result: binding record used by transaction steps.

Source: packages/slingshot-core/src/operations.ts

Outcome that can be stated truthfully after a commit failure.

Source: packages/slingshot-core/src/transactions.ts

Resolved method for a TransactionOpConfig.

Executes a sequence of named steps in order. Each step’s result is available to subsequent steps via zero-based 'result:N.field' references. Returns all step results as an array.

Source: packages/slingshot-core/src/operations.ts

One statically valid step in an op.transaction.

Named semantic steps carry the exact configured operation they will invoke. This prevents runtime reconstruction of atomic backend behavior through generic read/modify/write calls.

Source: packages/slingshot-core/src/operations.ts

Result value produced by one declarative transaction step.

Source: packages/slingshot-core/src/transactions.ts

Stores reserved for real framework-owned transaction implementations.

Source: packages/slingshot-core/src/transactions.ts

Resolved method for a TransitionOpConfig with returns: 'boolean'.

Attempts a state-machine transition. Returns true if the transition succeeded (entity was in an allowed from state), false if the current state did not permit the transition. Never throws for a guard failure — only throws on unexpected DB errors.

Source: packages/slingshot-core/src/operations.ts

Resolved method for a TransitionOpConfig without returns: 'boolean'.

Attempts a state-machine transition and returns the updated entity on success, or null if the guard blocked it (entity was not in an allowed from state).

Source: packages/slingshot-core/src/operations.ts

// a return type that points at slingshot-core/dist/src/operations and // raises TS2742. LookupOneMethod`

Source: packages/slingshot-core/src/operations.ts

Best-effort binding input exposed for handler convenience.

Object bodies are merged with params/query at runtime. Array and primitive bodies are passed through directly because they cannot be meaningfully merged into a record.

Source: packages/slingshot-core/src/packageAuthoring.ts

Response metadata keyed by HTTP status code.

Source: packages/slingshot-core/src/packageAuthoring.ts

Resolved method for an UpsertOpConfig without the created flag.

Creates the entity if it doesn’t exist, updates it if it does. Returns only the final entity state, without indicating whether a create or update occurred.

Source: packages/slingshot-core/src/operations.ts

Resolved method for an UpsertOpConfig with returns: { entity: true, created: true }.

Creates the entity if it doesn’t exist, updates it if it does. Returns both the entity and a created flag indicating which path was taken.

Source: packages/slingshot-core/src/operations.ts

A function that converts Zod issues into a custom validation error response body.

Override this in your app config to control the shape of 400 validation errors. The default is defaultValidationErrorFormatter which produces DefaultValidationErrorBody.

Remarks: If the formatter throws, defaultHook catches the error and falls back to defaultValidationErrorFormatter automatically — a buggy custom formatter will not cause a 500. The formatter must be synchronous; async formatters are not supported.

Source: packages/slingshot-core/src/context.ts

Controls how adapters handle schema validation failures.

Source: packages/slingshot-core/src/eventTypes.ts

Standard publish function signature for broadcasting to a WebSocket room.

Defined in slingshot-core so plugins and packages can reference the type without importing from the framework layer (src/framework/lib/ws.ts).

The concrete implementation lives in the framework and is exposed via SlingshotContext.wsPublish. Plugins typically read it lazily from app context rather than threading callback props through package config.

Source: packages/slingshot-core/src/wsHelpers.ts

Define an entity — the entry point for the config-driven persistence system.

Validates the config (primary key presence, soft-delete field existence, index field references, pagination cursor fields, and search config) then returns a deep-frozen ResolvedEntityConfig with _pkField and _storageName derived automatically.

Remarks: Storage name derivation: _storageName is derived from name by converting to snake_case, applying English pluralisation rules, and prepending namespace_ when a namespace is provided. Examples:

Remarks: | Name | Namespace | _storageName | |---------------|------------|------------------------| | Message | 'chat' | 'chat_messages' | | MyEntity | 'chat' | 'chat_my_entities' | | Category | — | 'categories' | | Activity | — | 'activities' | | Box | — | 'boxes' | | Status | — | 'statuses' |

Remarks: Pluralisation rules applied in order: 1. Ends in y preceded by a consonant → replace y with ies (categorycategories, activityactivities). Vowel-preceded y (day, key) gets a plain s suffix. 2. Ends in s, x, z, sh, or ch → append es (boxboxes). 3. All other cases → append s.

Remarks: To override the derived name (e.g. for an irregular plural or a legacy table), set storage.sqlite.tableName / storage.postgres.tableName / storage.mongo.collectionName in EntityStorageHints. The _storageName value itself cannot be overridden — it is used as the canonical key for event bus routing and WebSocket room names regardless of backing-store table names.

Source: packages/slingshot-core/src/entityConfig.ts

Declare a package-owned non-entity route group and optional domain-local services.

Source: packages/slingshot-core/src/packageAuthoring.ts