@lastshotlabs/slingshot-core
npm install @lastshotlabs/slingshot-core
Functions
Section titled “Functions”applyPublicEntityExposure
Section titled “applyPublicEntityExposure”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function applyPublicEntityExposure<TValue>(adapter: TValue, exposure: PublicEntityExposureMetadata | undefined, context: { readonly entity: string; readonly contract?: string; readonly source?: string },): TValueSource: packages/slingshot-core/src/packageAuthoring.ts
assertMountPath
Section titled “assertMountPath”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 assertMountPath(pluginName: string, mountPath: string): voidSource: packages/slingshot-core/src/configValidation.ts
attachContext
Section titled “attachContext”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): voidSource: packages/slingshot-core/src/context/contextStore.ts
attachPostgresPoolRuntime
Section titled “attachPostgresPoolRuntime”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
function attachPostgresPoolRuntime(pool: object, runtime: PostgresPoolRuntime): voidSource: packages/slingshot-core/src/postgresRuntime.ts
AUTH_PLUGIN_STATE_KEY
Section titled “AUTH_PLUGIN_STATE_KEY”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
authorizeEventSubscriber
Section titled “authorizeEventSubscriber”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.
function authorizeEventSubscriber<K extends EventKey>(definition: EventDefinition<K>, principal: EventSubscriptionPrincipal, envelope: EventEnvelope<K>,): booleanSource: packages/slingshot-core/src/eventPublisher.ts
bestEffort
Section titled “bestEffort”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): voidSource: packages/slingshot-core/src/bestEffort.ts
buildHookServices
Section titled “buildHookServices”HookServices — typed accessors for out-of-request callbacks.
Auth lifecycle hooks, orchestration workflow hooks, and queue dead-letter callbacks
fire outside any Hono request context — there is no c to read state from. Without
a canonical contract these callbacks ended up starved differently in each plugin
(some got pluginState, others got only request metadata, others nothing at all).
HookServices is the shared shape every plugin’s out-of-request callbacks intersect
into their payload. Hook authors get the same typed accessors that
PackageDomainRouteContext exposes to package-authored route handlers, so the
ergonomics line up across request and non-request callsites:
postLogin: async ({ userId, services }) => {const adapter = services.entities.get(GuestIdentity); // typed via entity moduleconst mailer = services.capabilities.require(MailerCapability);await services.bus.emit('user.signed-in', { userId });}Plugins build a HookServices instance by calling buildHookServices() at the call
site of each hook, threading their own pluginState/bus/logger and the app’s
Hono reference. The framework supplies the shared
SlingshotContext.capabilityProviders map so capability lookups work identically to
those inside request handlers.
Worker-process boundary. Some adapters (notably the Temporal orchestration worker)
run hook code in a separate process where the framework’s app is not reachable.
Those callsites pass services: undefined rather than fabricate broken accessors.
Hook authors who need framework state from worker-mode code should restructure their
work to run at the workflow level (in-process) and thread data into the task input.
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; }): HookServicesSource: packages/slingshot-core/src/hookServices.ts
capabilityProviderKey
Section titled “capabilityProviderKey”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function capabilityProviderKey(handle: PackageCapabilityHandle<unknown>): stringSource: packages/slingshot-core/src/packageAuthoring.ts
createConsoleLogger
Section titled “createConsoleLogger”Structured logger contract used by prod-track packages.
The interface is deliberately small: four severity methods plus child()
for fields that should appear on every log line in a sub-component (request
id, plugin name, queue id, etc.). Implementations must never throw — log
sinks that crash the caller are worse than silent loss.
createConsoleLogger is the default — one JSON line per call written to the
underlying console method matching the level. noopLogger is the test
default for code paths that need a logger handle but no output.
function createConsoleLogger(opts?: { level?: LogLevel; base?: LogFields }): LoggerSource: packages/slingshot-core/src/observability/logger.ts
createCoreRegistrar
Section titled “createCoreRegistrar”Mutable bootstrap registrar that collects auth-boundary dependencies (route auth, cache adapters, email templates, …) from plugins, then drains them into a frozen CoreRegistrarSnapshot.
function createCoreRegistrar(): voidSource: packages/slingshot-core/src/coreRegistrar.ts
createDefaultFingerprintBuilder
Section titled “createDefaultFingerprintBuilder”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(): FingerprintBuilderSource: packages/slingshot-core/src/defaults/defaultFingerprint.ts
createDefaultIdentityResolver
Section titled “createDefaultIdentityResolver”Actor-based identity abstraction.
Decouples all framework consumers (guards, permissions, data scoping, audit,
entity routes) from specific auth-provider field names by mapping them into
the canonical Actor shape.
Custom auth integrations implement IdentityResolver to map their own
identity representation into the canonical Actor shape.
function createDefaultIdentityResolver(): IdentityResolverSource: packages/slingshot-core/src/identity.ts
createDefaultSubscriberAuthorizer
Section titled “createDefaultSubscriberAuthorizer”Validate an event definition, throwing if ownerPlugin is empty, no exposure
is declared, exposures are duplicated, or internal is mixed with external exposures.
function createDefaultSubscriberAuthorizer<K extends EventKey>(definition: Pick<EventDefinition<K>, 'exposure'>,): EventSubscriberAuthorizer<K>Source: packages/slingshot-core/src/eventDefinition.ts
createEntityRegistry
Section titled “createEntityRegistry”General-purpose entity registry.
Plugins that need to discover entities at runtime (search indexing, schema generation, admin UIs, migration tooling, documentation) use this registry.
Created by the framework during bootstrap, exposed to plugin lifecycle hooks
on SlingshotFrameworkConfig, and consumed by framework-owned services such as
search indexing.
function createEntityRegistry(): EntityRegistrySource: packages/slingshot-core/src/entityRegistry.ts
createEventDefinitionRegistry
Section titled “createEventDefinitionRegistry”Registry of EventDefinitions keyed by event name, freezable once all plugins have registered their events.
function createEventDefinitionRegistry(options: EventDefinitionRegistryOptions = {},): EventDefinitionRegistrySource: packages/slingshot-core/src/eventDefinitionRegistry.ts
createEventEnvelope
Section titled “createEventEnvelope”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
createEventPublisher
Section titled “createEventPublisher”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.
function createEventPublisher(options: CreateEventPublisherOptions): SlingshotEventsSource: packages/slingshot-core/src/eventPublisher.ts
createEventSchemaRegistry
Section titled “createEventSchemaRegistry”Result of validating an event payload against a registered schema.
function createEventSchemaRegistry(): EventSchemaRegistrySource: packages/slingshot-core/src/eventSchemaRegistry.ts
createEvictExpired
Section titled “createEvictExpired”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 createEvictExpired(intervalMs = EVICTION_INTERVAL_MS,): <K, V extendsSource: packages/slingshot-core/src/memoryEviction.ts
createInProcessAdapter
Section titled “createInProcessAdapter”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.
function createInProcessAdapter(serializationOpts?: EventBusSerializationOptions,): SlingshotEventBusSource: packages/slingshot-core/src/eventBus.ts
createInProcessMetricsEmitter
Section titled “createInProcessMetricsEmitter”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
function createInProcessMetricsEmitter(logger?: Logger): InProcessMetricsEmitterSource: packages/slingshot-core/src/metrics.ts
createMemoryCacheAdapter
Section titled “createMemoryCacheAdapter”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(): CacheAdapterSource: packages/slingshot-core/src/defaults/memoryCacheAdapter.ts
createMemoryOperationIdempotencyAdapter
Section titled “createMemoryOperationIdempotencyAdapter”Operation-level idempotency contract used by delivery and retry-aware packages (mail, push, notifications, orchestration) to dedup retried operations.
Remarks: This is distinct from the HTTP IdempotencyAdapter contract in ../idempotencyAdapter.ts, which is dedicated to the request-replay middleware (caching the full HTTP response for a given Idempotency-Key header).
Remarks: The contract here is keyed on a structured IdempotencyKey and stores an arbitrary payload (typed at the call site). Callers wrap their operation in withIdempotency so that retries skip work and replay the prior result.
function createMemoryOperationIdempotencyAdapter(opts?: { defaultTtlMs?: number; maxEntries?: number; }): IdempotencyAdapterSource: packages/slingshot-core/src/idempotency/index.ts
createMemoryRateLimitAdapter
Section titled “createMemoryRateLimitAdapter”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(): RateLimitAdapterSource: packages/slingshot-core/src/defaults/memoryRateLimit.ts
createNoopMetricsEmitter
Section titled “createNoopMetricsEmitter”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
function createNoopMetricsEmitter(): MetricsEmitterSource: packages/slingshot-core/src/metrics.ts
createPluginStateMap
Section titled “createPluginStateMap”Writable plugin state used internally by the framework bootstrap lifecycle.
function createPluginStateMap(entries?: Iterable<readonly [string, unknown]>,): PluginStateMapSource: packages/slingshot-core/src/pluginState.ts
createPostgresPoolRuntime
Section titled “createPostgresPoolRuntime”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
function createPostgresPoolRuntime(opts?: { migrationMode?: PostgresMigrationMode; healthcheckTimeoutMs?: number; }): PostgresPoolRuntimeSource: packages/slingshot-core/src/postgresRuntime.ts
createRawEventEnvelope
Section titled “createRawEventEnvelope”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 createRawEventEnvelope<K extends EventKey>(key: K, payload: SlingshotEventMap[K],): EventEnvelope<K>Source: packages/slingshot-core/src/eventEnvelope.ts
createRoute
Section titled “createRoute”The schema parameter type expected by zodOpenAPIRegistry.add().
function createRoute<T extends RouteConfig>(config: T): TSource: packages/slingshot-core/src/createRoute.ts
createRouter
Section titled “createRouter”A single field-level validation error detail produced by the default formatter.
function createRouter(): voidSource: packages/slingshot-core/src/context.ts
createRouterAdapter
Section titled “createRouterAdapter”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).
function createRouterAdapter(opts: RouterAdapterOptions): SlingshotEventBusSource: packages/slingshot-core/src/routerAdapter.ts
createSafeFetch
Section titled “createSafeFetch”Minimal local type for the subset of the undici Dispatcher we use. We
keep this local so callers do not need to import undici types directly.
function createSafeFetch(opts: SafeFetchOptions = {}): typeof fetchSource: packages/slingshot-core/src/http/safeFetch.ts
cursorPaginatedResponse
Section titled “cursorPaginatedResponse”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).
function cursorPaginatedResponse<T extends ZodType>(itemSchema: T, name: string): voidSource: packages/slingshot-core/src/pagination.ts
cursorParams
Section titled “cursorParams”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).
function cursorParams(defaults?: CursorParamDefaults): voidSource: packages/slingshot-core/src/pagination.ts
decodeCursor
Section titled “decodeCursor”Shared cursor encoding/decoding for adapter pagination.
All adapters encode cursors as base64-encoded JSON. The payload shape varies by domain (timestamps vs sequence numbers, id vs _id), so the encode/decode functions are generic over the payload type.
function decodeCursor<T extends object>(cursor: string, validate?: (parsed: unknown) => parsed is T,): T | nullSource: packages/slingshot-core/src/cursor.ts
decryptField
Section titled “decryptField”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 decryptField(ciphertext: string, keyConfig: DataEncryptionKey[]): stringSource: packages/slingshot-core/src/crypto.ts
deepFreeze
Section titled “deepFreeze”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): TSource: packages/slingshot-core/src/deepFreeze.ts
defaultHook
Section titled “defaultHook”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
defaultValidationErrorFormatter
Section titled “defaultValidationErrorFormatter”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
defineCapability
Section titled “defineCapability”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function defineCapability<TValue>(name: string): PackageCapabilityHandle<TValue>Source: packages/slingshot-core/src/packageAuthoring.ts
defineConfig
Section titled “defineConfig”Typed, env-validated app config — the canonical answer to “where does this setting come from and what shape must it have?”
Slingshot already has a secret-resolution layer (SecretRepository)
that answers “where does this VALUE come from” (env var, AWS SSM, Vault,
etc.). defineConfig answers the orthogonal question “what SHAPE does this
app require, and where do those typed fields live in env.” Most apps need
both; they’re complementary.
A config definition declares a namespace and a Zod schema. At app boot,
the framework reads process.env (or a custom source), maps each schema
field to a NAMESPACE_FIELD env var, validates the whole thing through Zod,
and caches the result. After boot, anywhere in your app, cfg.get() returns
the typed validated values — fail-fast at startup, not at the first request.
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
defineEvent
Section titled “defineEvent”Validate an event definition, throwing if ownerPlugin is empty, no exposure
is declared, exposures are duplicated, or internal is mixed with external exposures.
function defineEvent<K extends EventKey>(key: K, definition: Omit<EventDefinition<K>, 'key'>,): Readonly<EventDefinition<K>>Source: packages/slingshot-core/src/eventDefinition.ts
defineHandler
Section titled “defineHandler”Resolve the canonical Actor from a HandlerMeta object.
function defineHandler<TInput extends ZodTypeAny, TOutput extends ZodTypeAny>(config: HandlerConfig<TInput, TOutput>,): SlingshotHandler<TInput, TOutput>Source: packages/slingshot-core/src/handler.ts
defineHealthIndicator
Section titled “defineHealthIndicator”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
function defineHealthIndicator(indicator: HealthIndicator): HealthIndicatorSource: packages/slingshot-core/src/observability/health.ts
definePackage
Section titled “definePackage”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function definePackage(input: DefinePackageInput): SlingshotPackageDefinitionSource: packages/slingshot-core/src/packageAuthoring.ts
definePackageContract
Section titled “definePackageContract”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function definePackageContract<const TName extends string>(contractName: TName,): PackageContract<TName>Source: packages/slingshot-core/src/packageAuthoring.ts
definePluginStateKey
Section titled “definePluginStateKey”Writable plugin state used internally by the framework bootstrap lifecycle.
function definePluginStateKey<T>(name: string): PluginStateKey<T>Source: packages/slingshot-core/src/pluginState.ts
definePolicy
Section titled “definePolicy”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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.
function definePolicy<TRecord = unknown, TInput = unknown>(key: string, resolver: PolicyResolver<TRecord, TInput>,): PolicyToken<TRecord, TInput>Source: packages/slingshot-core/src/entityRouteConfig.ts
defineRequestScope
Section titled “defineRequestScope”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
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
disableRoutesSchema
Section titled “disableRoutesSchema”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[]): voidSource: packages/slingshot-core/src/configValidation.ts
emitPackageStabilityWarning
Section titled “emitPackageStabilityWarning”Maturity label for a Slingshot package, driving the runtime warning emitted for non-stable packages.
function emitPackageStabilityWarning(packageName: string, stability: Exclude<PackageStability, 'stable'>, detail?: string,): voidSource: packages/slingshot-core/src/stability.ts
encodeCursor
Section titled “encodeCursor”Shared cursor encoding/decoding for adapter pagination.
All adapters encode cursors as base64-encoded JSON. The payload shape varies by domain (timestamps vs sequence numbers, id vs _id), so the encode/decode functions are generic over the payload type.
function encodeCursor(payload: object): stringSource: packages/slingshot-core/src/cursor.ts
encryptField
Section titled “encryptField”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 encryptField(plaintext: string, keyConfig: DataEncryptionKey[]): stringSource: packages/slingshot-core/src/crypto.ts
entityChannelConfigSchema
Section titled “entityChannelConfigSchema”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
entityRef
Section titled “entityRef”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
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
entityRouteConfigSchema
Section titled “entityRouteConfigSchema”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
errorResponse
Section titled “errorResponse”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,): voidSource: packages/slingshot-core/src/errorResponse.ts
evaluateAuthUserAccess
Section titled “evaluateAuthUserAccess”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.
async function evaluateAuthUserAccess(runtime: AuthRuntimePeer, input: AuthUserAccessInput,): Promise<AuthUserAccessDecision>Source: packages/slingshot-core/src/authPeer.ts
evaluateFilter
Section titled “evaluateFilter”Runtime filter expression evaluator.
Pure function: takes a record, a filter expression, and resolved params, returns whether the record matches.
This is the runtime counterpart of the codegen filter compiler in slingshot-data/generators/filter.ts. Same semantics, different output: the compiler generates code strings, this evaluates live.
function evaluateFilter(record: Record<string, unknown>, filter: FilterExpression, params: Record<string, unknown> = {},): booleanSource: packages/slingshot-core/src/filterEvaluator.ts
eventHasExternalExposure
Section titled “eventHasExternalExposure”Validate an event definition, throwing if ownerPlugin is empty, no exposure
is declared, exposures are duplicated, or internal is mixed with external exposures.
function eventHasExternalExposure<K extends EventKey>(definition: Pick<EventDefinition<K>, 'exposure'>,): booleanSource: packages/slingshot-core/src/eventDefinition.ts
evictOldest
Section titled “evictOldest”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): voidSource: packages/slingshot-core/src/memoryEviction.ts
evictOldestArray
Section titled “evictOldestArray”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 evictOldestArray(arr: unknown[], maxEntries: number): voidSource: packages/slingshot-core/src/memoryEviction.ts
extractFilterParams
Section titled “extractFilterParams”Runtime filter expression evaluator.
Pure function: takes a record, a filter expression, and resolved params, returns whether the record matches.
This is the runtime counterpart of the codegen filter compiler in slingshot-data/generators/filter.ts. Same semantics, different output: the compiler generates code strings, this evaluates live.
function extractFilterParams(filter: FilterExpression): string[]Source: packages/slingshot-core/src/filterEvaluator.ts
extractMatchParams
Section titled “extractMatchParams”Runtime filter expression evaluator.
Pure function: takes a record, a filter expression, and resolved params, returns whether the record matches.
This is the runtime counterpart of the codegen filter compiler in slingshot-data/generators/filter.ts. Same semantics, different output: the compiler generates code strings, this evaluates live.
function extractMatchParams(match: Record<string, string | number | boolean>): string[]Source: packages/slingshot-core/src/filterEvaluator.ts
extractMentionsFromBody
Section titled “extractMentionsFromBody”Broadcast keywords that take precedence over user-ID mentions.
function extractMentionsFromBody(body: string): readonly string[]Source: packages/slingshot-core/src/contentParser.ts
Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
generateExample
Section titled “generateExample”Public API for generating fake data from any Zod schema.
function generateExample<T>(schema: { _zod: { def: { type: string } } }, overrides?: Record<string, unknown>,): TSource: packages/slingshot-core/src/faker/generateFromSchema.ts
generateFromSchema
Section titled “generateFromSchema”Public API for generating fake data from any Zod schema.
function generateFromSchema<T>(schema: { _zod: { def: { type: string } } }, opts: GenerateOptions = {},): TSource: packages/slingshot-core/src/faker/generateFromSchema.ts
generateMany
Section titled “generateMany”Public API for generating fake data from any Zod schema.
function generateMany<T>(schema: { _zod: { def: { type: string } } }, count: number, opts: GenerateOptions = {},): T[]Source: packages/slingshot-core/src/faker/generateFromSchema.ts
generateSecureToken
Section titled “generateSecureToken”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 generateSecureToken(): stringSource: packages/slingshot-core/src/crypto.ts
getActor
Section titled “getActor”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>): ActorSource: packages/slingshot-core/src/actorContext.ts
getActorId
Section titled “getActorId”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 getActorId(c: Context<AppEnv>): string | nullSource: packages/slingshot-core/src/actorContext.ts
getActorTenantId
Section titled “getActorTenantId”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 getActorTenantId(c: Context<AppEnv>): string | nullSource: packages/slingshot-core/src/actorContext.ts
getAuthRuntimePeer
Section titled “getAuthRuntimePeer”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.
function getAuthRuntimePeer(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): AuthRuntimePeerSource: packages/slingshot-core/src/authPeer.ts
getAuthRuntimePeerOrNull
Section titled “getAuthRuntimePeerOrNull”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.
function getAuthRuntimePeerOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): AuthRuntimePeer | nullSource: packages/slingshot-core/src/authPeer.ts
getCacheAdapter
Section titled “getCacheAdapter”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.
function getCacheAdapter(input: ContextCarrier, store: CacheStoreName): CacheAdapterSource: packages/slingshot-core/src/cache.ts
getCacheAdapterOrNull
Section titled “getCacheAdapterOrNull”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.
function getCacheAdapterOrNull(input: ContextCarrier, store: CacheStoreName,): CacheAdapter | nullSource: packages/slingshot-core/src/cache.ts
getClientIp
Section titled “getClientIp”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 getClientIp<E extends AppEnv>(c: Context<E>): stringSource: packages/slingshot-core/src/clientIp.ts
getClientIpFromRequest
Section titled “getClientIpFromRequest”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 getClientIpFromRequest(req: Request, trustProxy: false | number): stringSource: packages/slingshot-core/src/clientIp.ts
getContext
Section titled “getContext”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 getContext(app: object): SlingshotContextSource: packages/slingshot-core/src/context/contextStore.ts
getContextOrNull
Section titled “getContextOrNull”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 getContextOrNull(app: object): SlingshotContext | nullSource: packages/slingshot-core/src/context/contextStore.ts
getEmailTemplate
Section titled “getEmailTemplate”A static email template (subject/html/text) registered by a plugin and consumed by the mail plugin.
function getEmailTemplate(input: ContextCarrier, key: string): EmailTemplate | nullSource: packages/slingshot-core/src/emailTemplates.ts
getEmailTemplates
Section titled “getEmailTemplates”A static email template (subject/html/text) registered by a plugin and consumed by the mail plugin.
function getEmailTemplates(input: ContextCarrier): Record<string, EmailTemplate>Source: packages/slingshot-core/src/emailTemplates.ts
getEmbedsPeer
Section titled “getEmbedsPeer”Cross-package handle to the embeds plugin’s URL unfurling capability.
function getEmbedsPeer(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): EmbedsPeerSource: packages/slingshot-core/src/embedsPeer.ts
getEmbedsPeerOrNull
Section titled “getEmbedsPeerOrNull”Cross-package handle to the embeds plugin’s URL unfurling capability.
function getEmbedsPeerOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): EmbedsPeer | nullSource: packages/slingshot-core/src/embedsPeer.ts
getFingerprintBuilder
Section titled “getFingerprintBuilder”Builds a short fingerprint hash from stable HTTP request headers, used for unauthenticated bot detection and request fingerprinting.
function getFingerprintBuilder(input: ContextCarrier): FingerprintBuilderSource: packages/slingshot-core/src/rateLimit.ts
getPermissionsState
Section titled “getPermissionsState”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis the service account’s client ID or name; used for backend-to-backend trust grants that should not be confused with end-user permissions
function getPermissionsState(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PermissionsStateSource: packages/slingshot-core/src/permissions.ts
getPermissionsStateOrNull
Section titled “getPermissionsStateOrNull”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis the service account’s client ID or name; used for backend-to-backend trust grants that should not be confused with end-user permissions
function getPermissionsStateOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PermissionsState | nullSource: packages/slingshot-core/src/permissions.ts
getPluginState
Section titled “getPluginState”Writable plugin state used internally by the framework bootstrap lifecycle.
function getPluginState(input: PluginStateMap | PluginStateCarrier | object,): PluginStateMapSource: packages/slingshot-core/src/pluginState.ts
getPluginStateFromRequest
Section titled “getPluginStateFromRequest”Writable plugin state used internally by the framework bootstrap lifecycle.
function getPluginStateFromRequest(c: { get(key: string): unknown }): PluginStateMapSource: packages/slingshot-core/src/pluginState.ts
getPluginStateFromRequestOrNull
Section titled “getPluginStateFromRequestOrNull”Writable plugin state used internally by the framework bootstrap lifecycle.
function getPluginStateFromRequestOrNull(c: { get(key: string): unknown; }): PluginStateMap | nullSource: packages/slingshot-core/src/pluginState.ts
getPluginStateOrNull
Section titled “getPluginStateOrNull”Writable plugin state used internally by the framework bootstrap lifecycle.
function getPluginStateOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PluginStateMap | nullSource: packages/slingshot-core/src/pluginState.ts
getPolicyResolverKey
Section titled “getPolicyResolverKey”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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.
function getPolicyResolverKey(resolver: string | PolicyTokenRef): stringSource: packages/slingshot-core/src/entityRouteConfig.ts
getPostgresPoolRuntime
Section titled “getPostgresPoolRuntime”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
function getPostgresPoolRuntime(pool: object): PostgresPoolRuntime | nullSource: packages/slingshot-core/src/postgresRuntime.ts
getPublishedInteractionsPeerOrNull
Section titled “getPublishedInteractionsPeerOrNull”Cross-package handle for resolving and updating interactive message components published by a peer package.
function getPublishedInteractionsPeerOrNull<TPeer extends PublishedInteractionsPeer>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, pluginKey: string,): TPeer | nullSource: packages/slingshot-core/src/publishedInteractionsPeer.ts
getPushFormatterPeer
Section titled “getPushFormatterPeer”Shape of a formatted push notification: title plus optional body, data, icon, badge, and URL.
function getPushFormatterPeer(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PushFormatterPeerSource: packages/slingshot-core/src/pushPeer.ts
getPushFormatterPeerOrNull
Section titled “getPushFormatterPeerOrNull”Shape of a formatted push notification: title plus optional body, data, icon, badge, and URL.
function getPushFormatterPeerOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): PushFormatterPeer | nullSource: packages/slingshot-core/src/pushPeer.ts
getRateLimitAdapter
Section titled “getRateLimitAdapter”Builds a short fingerprint hash from stable HTTP request headers, used for unauthenticated bot detection and request fingerprinting.
function getRateLimitAdapter(input: ContextCarrier): RateLimitAdapterSource: packages/slingshot-core/src/rateLimit.ts
getRequestActorResolver
Section titled “getRequestActorResolver”Resolves the connecting actor for framework WebSocket/SSE upgrades without depending on the auth plugin; registered by the auth plugin during setup.
function getRequestActorResolver(input: ContextCarrier): RequestActorResolverSource: packages/slingshot-core/src/requestActorResolver.ts
getRequestActorResolverOrNull
Section titled “getRequestActorResolverOrNull”Resolves the connecting actor for framework WebSocket/SSE upgrades without depending on the auth plugin; registered by the auth plugin during setup.
function getRequestActorResolverOrNull(input: ContextCarrier): RequestActorResolver | nullSource: packages/slingshot-core/src/requestActorResolver.ts
getRequestScoped
Section titled “getRequestScoped”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
async function getRequestScoped<T>(c: Context, scope: RequestScope<T>): Promise<T>Source: packages/slingshot-core/src/requestScope.ts
getRequestScopeStore
Section titled “getRequestScopeStore”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
function getRequestScopeStore(c: Context): RequestScopeStore | undefinedSource: packages/slingshot-core/src/requestScope.ts
getRequestTenantId
Section titled “getRequestTenantId”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 getRequestTenantId(c: Context<AppEnv>): string | nullSource: packages/slingshot-core/src/actorContext.ts
getRouteAuth
Section titled “getRouteAuth”A guard that runs after authentication, in registration order; the first to return a PostAuthGuardFailure short-circuits the request.
function getRouteAuth(input: ContextCarrier): RouteAuthRegistrySource: packages/slingshot-core/src/routeAuth.ts
getRouteAuthOrNull
Section titled “getRouteAuthOrNull”A guard that runs after authentication, in registration order; the first to return a PostAuthGuardFailure short-circuits the request.
function getRouteAuthOrNull(input: ContextCarrier): RouteAuthRegistry | nullSource: packages/slingshot-core/src/routeAuth.ts
getSearchPluginRuntime
Section titled “getSearchPluginRuntime”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
function getSearchPluginRuntime(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): SearchPluginRuntimeSource: packages/slingshot-core/src/searchPluginRuntime.ts
getSearchPluginRuntimeOrNull
Section titled “getSearchPluginRuntimeOrNull”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
function getSearchPluginRuntimeOrNull(input: PluginStateMap | PluginStateCarrier | object | null | undefined,): SearchPluginRuntime | nullSource: packages/slingshot-core/src/searchPluginRuntime.ts
getSlingshotCtx
Section titled “getSlingshotCtx”A single field-level validation error detail produced by the default formatter.
function getSlingshotCtx(c: Context<AppEnv>): SlingshotContextSource: packages/slingshot-core/src/context.ts
hashToken
Section titled “hashToken”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 hashToken(token: string): stringSource: packages/slingshot-core/src/crypto.ts
hmacSign
Section titled “hmacSign”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 hmacSign(input: string, secret: string | string[]): stringSource: packages/slingshot-core/src/crypto.ts
Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});function index(fields: string[], opts?: { direction?: 'asc' | 'desc'; unique?: boolean },): IndexDefSource: packages/slingshot-core/src/entityConfig.ts
inspectPackage
Section titled “inspectPackage”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function inspectPackage(pkg: SlingshotPackageDefinition): PackageInspectionSource: packages/slingshot-core/src/packageAuthoring.ts
isEncryptedField
Section titled “isEncryptedField”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 isEncryptedField(value: string): booleanSource: packages/slingshot-core/src/crypto.ts
isEventEnvelope
Section titled “isEventEnvelope”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 isEventEnvelope<K extends EventKey = EventKey>(value: unknown, key?: K,): value is EventEnvelope<K>Source: packages/slingshot-core/src/eventEnvelope.ts
isHttpError
Section titled “isHttpError”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.
function isHttpError(err: unknown): err is HttpErrorSource: packages/slingshot-core/src/errors.ts
isPackageRegistered
Section titled “isPackageRegistered”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function isPackageRegistered(app: object, packageName: string): booleanSource: packages/slingshot-core/src/packageAuthoring.ts
isPluginStateSealed
Section titled “isPluginStateSealed”Writable plugin state used internally by the framework bootstrap lifecycle.
function isPluginStateSealed(pluginState: PluginStateMap): booleanSource: packages/slingshot-core/src/pluginState.ts
isPolicyToken
Section titled “isPolicyToken”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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.
function isPolicyToken(value: unknown): value is PolicyTokenRefSource: packages/slingshot-core/src/entityRouteConfig.ts
isPrivateOrLoopbackIp
Section titled “isPrivateOrLoopbackIp”Minimal local type for the subset of the undici Dispatcher we use. We
keep this local so callers do not need to import undici types directly.
function isPrivateOrLoopbackIp(ip: string, family: 4 | 6): booleanSource: packages/slingshot-core/src/http/safeFetch.ts
isPublicPath
Section titled “isPublicPath”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): booleanSource: packages/slingshot-core/src/publicPath.ts
isValidationError
Section titled “isValidationError”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.
function isValidationError(err: unknown): err is ValidationErrorSource: packages/slingshot-core/src/errors.ts
isValidRoomName
Section titled “isValidRoomName”Shared WebSocket utility helpers.
Extracted to slingshot-core so both the framework (src/framework/lib/ws.ts)
and entity packages (slingshot-entity) can import without creating a
cross-layer dependency.
function isValidRoomName(room: string): booleanSource: packages/slingshot-core/src/wsHelpers.ts
loadConfigs
Section titled “loadConfigs”Typed, env-validated app config — the canonical answer to “where does this setting come from and what shape must it have?”
Slingshot already has a secret-resolution layer (SecretRepository)
that answers “where does this VALUE come from” (env var, AWS SSM, Vault,
etc.). defineConfig answers the orthogonal question “what SHAPE does this
app require, and where do those typed fields live in env.” Most apps need
both; they’re complementary.
A config definition declares a namespace and a Zod schema. At app boot,
the framework reads process.env (or a custom source), maps each schema
field to a NAMESPACE_FIELD env var, validates the whole thing through Zod,
and caches the result. After boot, anywhere in your app, cfg.get() returns
the typed validated values — fail-fast at startup, not at the first request.
function loadConfigs(configs: readonly ConfigDefinition<unknown>[], env: Readonly<Record<string, string | undefined>> = process.env as Readonly< Record<string, string | undefined> >,): voidSource: packages/slingshot-core/src/config.ts
makeIdempotencyKey
Section titled “makeIdempotencyKey”Operation-level idempotency contract used by delivery and retry-aware packages (mail, push, notifications, orchestration) to dedup retried operations.
Remarks: This is distinct from the HTTP IdempotencyAdapter contract in ../idempotencyAdapter.ts, which is dedicated to the request-replay middleware (caching the full HTTP response for a given Idempotency-Key header).
Remarks: The contract here is keyed on a structured IdempotencyKey and stores an arbitrary payload (typed at the call site). Callers wrap their operation in withIdempotency so that retries skip work and replay the prior result.
function makeIdempotencyKey(parts: ReadonlyArray<string | number>): IdempotencyKeySource: packages/slingshot-core/src/idempotency/index.ts
matchSubscriberToScope
Section titled “matchSubscriberToScope”Validate an event definition, throwing if ownerPlugin is empty, no exposure
is declared, exposures are duplicated, or internal is mixed with external exposures.
function matchSubscriberToScope(principal: EventSubscriptionPrincipal, scope: EventScope | null, exposure: readonly EventExposure[],): booleanSource: packages/slingshot-core/src/eventDefinition.ts
maybeAutoRegister
Section titled “maybeAutoRegister”The schema parameter type expected by zodOpenAPIRegistry.add().
function maybeAutoRegister(exportName: string, value: unknown): voidSource: packages/slingshot-core/src/createRoute.ts
maybeEntityAdapter
Section titled “maybeEntityAdapter”Writable plugin state used internally by the framework bootstrap lifecycle.
function maybeEntityAdapter<TAdapter extends object = object>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, lookup: EntityAdapterLookupInput<TAdapter>,): TAdapter | nullSource: packages/slingshot-core/src/pluginState.ts
offsetParams
Section titled “offsetParams”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).
function offsetParams(defaults?: OffsetParamDefaults): voidSource: packages/slingshot-core/src/pagination.ts
PACKAGE_CAPABILITIES_PREFIX
Section titled “PACKAGE_CAPABILITIES_PREFIX”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
paginatedResponse
Section titled “paginatedResponse”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).
function paginatedResponse<T extends ZodType>(itemSchema: T, name: string): voidSource: packages/slingshot-core/src/pagination.ts
parseBody
Section titled “parseBody”Broadcast keywords that take precedence over user-ID mentions.
function parseBody(body: string | undefined | null, format: ContentFormat = 'markdown',): ParsedBodySource: packages/slingshot-core/src/contentParser.ts
parseContentTokens
Section titled “parseContentTokens”Broadcast keywords that take precedence over user-ID mentions.
function parseContentTokens(body: string): ParsedContentSource: packages/slingshot-core/src/contentParser.ts
parseCursorParams
Section titled “parseCursorParams”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).
function parseCursorParams(raw: { limit?: string; cursor?: string }, defaults?: CursorParamDefaults,): ParsedCursorParamsSource: packages/slingshot-core/src/pagination.ts
parseOffsetParams
Section titled “parseOffsetParams”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).
function parseOffsetParams(raw: { limit?: string; offset?: string }, defaults?: OffsetParamDefaults,): ParsedOffsetParamsSource: packages/slingshot-core/src/pagination.ts
PERMISSIONS_STATE_KEY
Section titled “PERMISSIONS_STATE_KEY”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
provideCapability
Section titled “provideCapability”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function provideCapability<TValue>(capability: PackageCapabilityHandle<TValue>, resolve: PublishedPackageCapability<TValue>['resolve'],): PublishedPackageCapability<TValue>Source: packages/slingshot-core/src/packageAuthoring.ts
publishEntityAdaptersState
Section titled “publishEntityAdaptersState”Writable plugin state used internally by the framework bootstrap lifecycle.
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
publishPluginState
Section titled “publishPluginState”Writable plugin state used internally by the framework bootstrap lifecycle.
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, ): voidSource: packages/slingshot-core/src/pluginState.ts
readPluginState
Section titled “readPluginState”Writable plugin state used internally by the framework bootstrap lifecycle.
function readPluginState<T>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, key: PluginStateKey<T>,): T | undefinedSource: packages/slingshot-core/src/pluginState.ts
registerPluginCapabilities
Section titled “registerPluginCapabilities”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
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
registerSchema
Section titled “registerSchema”The schema parameter type expected by zodOpenAPIRegistry.add().
function registerSchema<T extends ZodType>(name: string, schema: T): TSource: packages/slingshot-core/src/createRoute.ts
registerSchemas
Section titled “registerSchemas”The schema parameter type expected by zodOpenAPIRegistry.add().
Source: packages/slingshot-core/src/createRoute.ts
relation
Section titled “relation”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
requireEntityAdapter
Section titled “requireEntityAdapter”Writable plugin state used internally by the framework bootstrap lifecycle.
function requireEntityAdapter<TAdapter extends object = object>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, lookup: EntityAdapterLookupInput<TAdapter>,): TAdapterSource: packages/slingshot-core/src/pluginState.ts
requirePluginState
Section titled “requirePluginState”Writable plugin state used internally by the framework bootstrap lifecycle.
function requirePluginState<T>(input: PluginStateMap | PluginStateCarrier | object | null | undefined, key: PluginStateKey<T>,): TSource: packages/slingshot-core/src/pluginState.ts
RESOLVE_COMPOSITE_FACTORIES
Section titled “RESOLVE_COMPOSITE_FACTORIES”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
RESOLVE_ENTITY_FACTORIES
Section titled “RESOLVE_ENTITY_FACTORIES”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
RESOLVE_REINDEX_SOURCE
Section titled “RESOLVE_REINDEX_SOURCE”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
resolveActor
Section titled “resolveActor”Resolve the canonical Actor from a HandlerMeta object.
function resolveActor(meta: HandlerMeta): ActorSource: packages/slingshot-core/src/handler.ts
resolveCapabilityValue
Section titled “resolveCapabilityValue”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
function resolveCapabilityValue<TValue>(ctx: { readonly capabilityProviders?: ReadonlyMap<string, string>; readonly pluginState: PluginStateMap; }, capability: PackageCapabilityHandle<TValue>,): TValue | undefinedSource: packages/slingshot-core/src/packageAuthoring.ts
resolveContext
Section titled “resolveContext”A value that either IS a SlingshotContext or is an app instance that HAS one attached.
Used as the parameter type for all context-accessor helpers (getRequestActorResolver,
getRateLimitAdapter, getCacheAdapter, etc.) so callers can pass either
the raw context or the app without ceremony.
Remarks: Branded-context pattern: ContextCarrier is intentionally typed as SlingshotContext | object rather than SlingshotContext | Hono to avoid importing the Hono type into contextAccess.ts and to support any future app container that happens to carry a context via getContext. The actual discrimination between “is a context” and “has a context” is performed at runtime by checking for the internal context brand installed by attachContext(). This avoids property-shape guessing, which can false-positive on unrelated objects that happen to expose fields like config or cacheAdapters.
function resolveContext(input: ContextCarrier): SlingshotContextSource: packages/slingshot-core/src/context/contextAccess.ts
resolveMatch
Section titled “resolveMatch”Runtime filter expression evaluator.
Pure function: takes a record, a filter expression, and resolved params, returns whether the record matches.
This is the runtime counterpart of the codegen filter compiler in slingshot-data/generators/filter.ts. Same semantics, different output: the compiler generates code strings, this evaluates live.
function resolveMatch(match: Record<string, string | number | boolean>, params: Record<string, unknown>,): Record<string, unknown>Source: packages/slingshot-core/src/filterEvaluator.ts
resolveOpConfig
Section titled “resolveOpConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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.
function resolveOpConfig(routeConfig: EntityRouteConfig, opName: string,): RouteOperationConfig | undefinedSource: packages/slingshot-core/src/entityRouteConfig.ts
resolvePluginState
Section titled “resolvePluginState”Writable plugin state used internally by the framework bootstrap lifecycle.
function resolvePluginState(input: PluginStateMap | PluginStateCarrier | null | undefined,): PluginStateMap | nullSource: packages/slingshot-core/src/pluginState.ts
resolveRepo
Section titled “resolveRepo”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
function resolveRepo<T>(factories: RepoFactories<T>, storeType: StoreType, infra: StoreInfra,): TSource: packages/slingshot-core/src/storeInfra.ts
resolveRepoAsync
Section titled “resolveRepoAsync”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
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
Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
routeKey
Section titled “routeKey”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.
function routeKey<M extends string, P extends string>(method: M, path: P): RouteKey<M, P>Source: packages/slingshot-core/src/routeOverrides.ts
runSubsystemMigrations
Section titled “runSubsystemMigrations”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>,): voidSource: packages/slingshot-core/src/sqliteMigrations.ts
safeJoin
Section titled “safeJoin”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.
function safeJoin(baseDir: string, userPath: string): stringSource: packages/slingshot-core/src/lib/safePath.ts
sanitizeHeaderValue
Section titled “sanitizeHeaderValue”CRLF / NUL injection guards for header-like and log-like sinks.
When user-controlled values flow into HTTP headers, email headers, queue
message headers, or log lines without sanitization, an attacker can inject
carriage-return / line-feed sequences (\r\n, \n) and forge additional
headers, split log records, or hide malicious payloads in logs. This module
provides the two helpers prod-track packages should use at every boundary
that emits a header value or log fragment derived from external input.
Two complementary functions are exposed:
sanitizeHeaderValue— strict, throwsHeaderInjectionErrorwhen the input contains\r,\n, or NUL. Use at HTTP / email / queue header sinks where silent stripping would mask other bugs.sanitizeLogValue— lenient, escapes the same control characters so they appear as literal\\r/\\n/\\0in the log output. Logging must never throw, so this function never throws.
function sanitizeHeaderValue(value: string, header?: string): stringSource: packages/slingshot-core/src/lib/sanitize.ts
sanitizeLogValue
Section titled “sanitizeLogValue”CRLF / NUL injection guards for header-like and log-like sinks.
When user-controlled values flow into HTTP headers, email headers, queue
message headers, or log lines without sanitization, an attacker can inject
carriage-return / line-feed sequences (\r\n, \n) and forge additional
headers, split log records, or hide malicious payloads in logs. This module
provides the two helpers prod-track packages should use at every boundary
that emits a header value or log fragment derived from external input.
Two complementary functions are exposed:
sanitizeHeaderValue— strict, throwsHeaderInjectionErrorwhen the input contains\r,\n, or NUL. Use at HTTP / email / queue header sinks where silent stripping would mask other bugs.sanitizeLogValue— lenient, escapes the same control characters so they appear as literal\\r/\\n/\\0in the log output. Logging must never throw, so this function never throws.
function sanitizeLogValue(value: unknown): stringSource: packages/slingshot-core/src/lib/sanitize.ts
sealPluginState
Section titled “sealPluginState”Writable plugin state used internally by the framework bootstrap lifecycle.
function sealPluginState(pluginState: PluginStateMap): voidSource: packages/slingshot-core/src/pluginState.ts
SECURITY_EVENT_TYPES
Section titled “SECURITY_EVENT_TYPES”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
setRequestScopeStore
Section titled “setRequestScopeStore”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
function setRequestScopeStore(c: Context, store: RequestScopeStore): voidSource: packages/slingshot-core/src/requestScope.ts
setStandaloneClientIp
Section titled “setStandaloneClientIp”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 setStandaloneClientIp(req: Request, value: string): voidSource: packages/slingshot-core/src/clientIp.ts
setStandaloneTrustProxy
Section titled “setStandaloneTrustProxy”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): voidSource: packages/slingshot-core/src/clientIp.ts
sha256
Section titled “sha256”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 sha256(input: string): stringSource: packages/slingshot-core/src/crypto.ts
shouldMountRoute
Section titled “shouldMountRoute”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.
function shouldMountRoute(method: string, path: string, disabledRoutes?: readonly string[],): booleanSource: packages/slingshot-core/src/routeOverrides.ts
stripContentTokens
Section titled “stripContentTokens”Broadcast keywords that take precedence over user-ID mentions.
function stripContentTokens(body: string): stringSource: packages/slingshot-core/src/contentParser.ts
SUPER_ADMIN_ROLE
Section titled “SUPER_ADMIN_ROLE”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
timeoutSignal
Section titled “timeoutSignal”Promise and AbortSignal timeout helpers.
withTimeout wraps an arbitrary promise and rejects with TimeoutError
if the configured deadline elapses before the promise settles. The internal
timer is always cleared when the wrapped promise resolves or rejects, so a
fast-settling promise will not produce a delayed rejection from a stale
timer.
timeoutSignal returns an AbortSignal that is aborted after timeoutMs.
Useful for libraries (HTTP clients, streams) that accept an AbortSignal
directly and do not need a wrapping promise.
function timeoutSignal(timeoutMs: number): AbortSignalSource: packages/slingshot-core/src/concurrency/withTimeout.ts
timingSafeEqual
Section titled “timingSafeEqual”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): booleanSource: packages/slingshot-core/src/crypto.ts
toHonoPath
Section titled “toHonoPath”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 toHonoPath(path: string): stringSource: packages/slingshot-core/src/mount.ts
toOpenApiPath
Section titled “toOpenApiPath”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): stringSource: packages/slingshot-core/src/mount.ts
validateAdapterShape
Section titled “validateAdapterShape”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 validateAdapterShape(pluginName: string, adapterLabel: string, adapter: unknown, requiredMethods: string[],): voidSource: packages/slingshot-core/src/configValidation.ts
validateEntityChannelConfig
Section titled “validateEntityChannelConfig”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.
function validateEntityChannelConfig(config: unknown): voidSource: packages/slingshot-core/src/entityChannelConfigSchema.ts
validateEntityRouteConfig
Section titled “validateEntityRouteConfig”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').
function validateEntityRouteConfig(config: unknown): voidSource: packages/slingshot-core/src/entityRouteConfigSchema.ts
validateEventDefinition
Section titled “validateEventDefinition”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>): voidSource: packages/slingshot-core/src/eventDefinition.ts
validateEventPayload
Section titled “validateEventPayload”Result of validating an event payload against a registered schema.
function validateEventPayload(event: string, payload: unknown, registry: EventSchemaRegistry | undefined, mode: ValidationMode, logger?: Logger,): unknownSource: packages/slingshot-core/src/eventSchemaRegistry.ts
validateGrant
Section titled “validateGrant”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis the service account’s client ID or name; used for backend-to-backend trust grants that should not be confused with end-user permissions
function validateGrant(grant: Omit<PermissionGrant, 'id' | 'grantedAt'>): voidSource: packages/slingshot-core/src/permissions.ts
validatePluginConfig
Section titled “validatePluginConfig”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 validatePluginConfig<S extends z.ZodType>(pluginName: string, rawConfig: unknown, schema: S, logger?: Logger,): z.infer<S>Source: packages/slingshot-core/src/configValidation.ts
withIdempotency
Section titled “withIdempotency”Operation-level idempotency contract used by delivery and retry-aware packages (mail, push, notifications, orchestration) to dedup retried operations.
Remarks: This is distinct from the HTTP IdempotencyAdapter contract in ../idempotencyAdapter.ts, which is dedicated to the request-replay middleware (caching the full HTTP response for a given Idempotency-Key header).
Remarks: The contract here is keyed on a structured IdempotencyKey and stores an arbitrary payload (typed at the call site). Callers wrap their operation in withIdempotency so that retries skip work and replay the prior result.
async function withIdempotency<T>(adapter: IdempotencyAdapter, key: IdempotencyKey, fn: () => Promise<T>, opts?: WithIdempotencyOptions,): Promise<Source: packages/slingshot-core/src/idempotency/index.ts
withSecurity
Section titled “withSecurity”The schema parameter type expected by zodOpenAPIRegistry.add().
function withSecurity<T extends RouteConfig>(route: T, ...schemes: Array<Record<string, string[]>>): TSource: packages/slingshot-core/src/createRoute.ts
withTimeout
Section titled “withTimeout”Promise and AbortSignal timeout helpers.
withTimeout wraps an arbitrary promise and rejects with TimeoutError
if the configured deadline elapses before the promise settles. The internal
timer is always cleared when the wrapped promise resolves or rejects, so a
fast-settling promise will not produce a delayed rejection from a stale
timer.
timeoutSignal returns an AbortSignal that is aborted after timeoutMs.
Useful for libraries (HTTP clients, streams) that accept an AbortSignal
directly and do not need a wrapping promise.
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label?: string): Promise<T>Source: packages/slingshot-core/src/concurrency/withTimeout.ts
Constants
Section titled “Constants”ANONYMOUS_ACTOR
Section titled “ANONYMOUS_ACTOR”Actor-based identity abstraction.
Decouples all framework consumers (guards, permissions, data scoping, audit,
entity routes) from specific auth-provider field names by mapping them into
the canonical Actor shape.
Custom auth integrations implement IdentityResolver to map their own
identity representation into the canonical Actor shape.
Source: packages/slingshot-core/src/identity.ts
assetRefSchema
Section titled “assetRefSchema”Zod schema for voice message metadata.
Source: packages/slingshot-core/src/content.schemas.ts
CHAT_PLUGIN_STATE_KEY
Section titled “CHAT_PLUGIN_STATE_KEY”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
COMMUNITY_PLUGIN_STATE_KEY
Section titled “COMMUNITY_PLUGIN_STATE_KEY”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
contactDataSchema
Section titled “contactDataSchema”Zod schema for voice message metadata.
Source: packages/slingshot-core/src/content.schemas.ts
COOKIE_CSRF_TOKEN
Section titled “COOKIE_CSRF_TOKEN”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
COOKIE_REFRESH_TOKEN
Section titled “COOKIE_REFRESH_TOKEN”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
COOKIE_TOKEN
Section titled “COOKIE_TOKEN”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_MAX_ENTRIES
Section titled “DEFAULT_MAX_ENTRIES”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.
Source: packages/slingshot-core/src/memoryEviction.ts
EMBEDS_PLUGIN_STATE_KEY
Section titled “EMBEDS_PLUGIN_STATE_KEY”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
HEADER_CSRF_TOKEN
Section titled “HEADER_CSRF_TOKEN”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
HEADER_IDEMPOTENCY_KEY
Section titled “HEADER_IDEMPOTENCY_KEY”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
HEADER_REFRESH_TOKEN
Section titled “HEADER_REFRESH_TOKEN”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
HEADER_REQUEST_ID
Section titled “HEADER_REQUEST_ID”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
HEADER_SIGNATURE
Section titled “HEADER_SIGNATURE”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
HEADER_TIMESTAMP
Section titled “HEADER_TIMESTAMP”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
HEADER_USER_TOKEN
Section titled “HEADER_USER_TOKEN”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
JSON_SERIALIZER
Section titled “JSON_SERIALIZER”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
locationDataSchema
Section titled “locationDataSchema”Zod schema for voice message metadata.
Source: packages/slingshot-core/src/content.schemas.ts
MAX_CONTENT_ATTACHMENTS
Section titled “MAX_CONTENT_ATTACHMENTS”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
MAX_CONTENT_BODY_LENGTH
Section titled “MAX_CONTENT_BODY_LENGTH”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
MAX_CONTENT_MENTIONS
Section titled “MAX_CONTENT_MENTIONS”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
noopLogger
Section titled “noopLogger”Structured logger contract used by prod-track packages.
The interface is deliberately small: four severity methods plus child()
for fields that should appear on every log line in a sub-component (request
id, plugin name, queue id, etc.). Implementations must never throw — log
sinks that crash the caller are worse than silent loss.
createConsoleLogger is the default — one JSON line per call written to the
underlying console method matching the level. noopLogger is the test
default for code paths that need a logger handle but no output.
Source: packages/slingshot-core/src/observability/logger.ts
quotePreviewSchema
Section titled “quotePreviewSchema”Zod schema for voice message metadata.
Source: packages/slingshot-core/src/content.schemas.ts
SEARCH_PLUGIN_STATE_KEY
Section titled “SEARCH_PLUGIN_STATE_KEY”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
Source: packages/slingshot-core/src/searchPluginRuntime.ts
systemEventDataSchema
Section titled “systemEventDataSchema”Zod schema for voice message metadata.
Source: packages/slingshot-core/src/content.schemas.ts
Classes
Section titled “Classes”HandlerError
Section titled “HandlerError”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
HeaderInjectionError
Section titled “HeaderInjectionError”CRLF / NUL injection guards for header-like and log-like sinks.
When user-controlled values flow into HTTP headers, email headers, queue
message headers, or log lines without sanitization, an attacker can inject
carriage-return / line-feed sequences (\r\n, \n) and forge additional
headers, split log records, or hide malicious payloads in logs. This module
provides the two helpers prod-track packages should use at every boundary
that emits a header value or log fragment derived from external input.
Two complementary functions are exposed:
sanitizeHeaderValue— strict, throwsHeaderInjectionErrorwhen the input contains\r,\n, or NUL. Use at HTTP / email / queue header sinks where silent stripping would mask other bugs.sanitizeLogValue— lenient, escapes the same control characters so they appear as literal\\r/\\n/\\0in the log output. Logging must never throw, so this function never throws.
Source: packages/slingshot-core/src/lib/sanitize.ts
HttpError
Section titled “HttpError”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
IdempotencyCacheHit
Section titled “IdempotencyCacheHit”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
InProcessAdapter
Section titled “InProcessAdapter”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
JsonEventSerializer
Section titled “JsonEventSerializer”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
PathTraversalError
Section titled “PathTraversalError”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
SafeFetchBlockedError
Section titled “SafeFetchBlockedError”Minimal local type for the subset of the undici Dispatcher we use. We
keep this local so callers do not need to import undici types directly.
Source: packages/slingshot-core/src/http/safeFetch.ts
SafeFetchDnsError
Section titled “SafeFetchDnsError”Minimal local type for the subset of the undici Dispatcher we use. We
keep this local so callers do not need to import undici types directly.
Source: packages/slingshot-core/src/http/safeFetch.ts
SlingshotError
Section titled “SlingshotError”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
TemplateNotFoundError
Section titled “TemplateNotFoundError”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
TimeoutError
Section titled “TimeoutError”Promise and AbortSignal timeout helpers.
withTimeout wraps an arbitrary promise and rejects with TimeoutError
if the configured deadline elapses before the promise settles. The internal
timer is always cleared when the wrapped promise resolves or rejects, so a
fast-settling promise will not produce a delayed rejection from a stale
timer.
timeoutSignal returns an AbortSignal that is aborted after timeoutMs.
Useful for libraries (HTTP clients, streams) that accept an AbortSignal
directly and do not need a wrapping promise.
Source: packages/slingshot-core/src/concurrency/withTimeout.ts
UnsupportedAdapterFeatureError
Section titled “UnsupportedAdapterFeatureError”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
ValidationError
Section titled “ValidationError”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
Interfaces
Section titled “Interfaces”Actor-based identity abstraction.
Decouples all framework consumers (guards, permissions, data scoping, audit,
entity routes) from specific auth-provider field names by mapping them into
the canonical Actor shape.
Custom auth integrations implement IdentityResolver to map their own
identity representation into the canonical Actor shape.
Source: packages/slingshot-core/src/identity.ts
AdminAccessProvider
Section titled “AdminAccessProvider”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
AdminPrincipal
Section titled “AdminPrincipal”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
AfterInvokeArgs
Section titled “AfterInvokeArgs”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
AggregateOpConfig
Section titled “AggregateOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ArrayPullOpConfig
Section titled “ArrayPullOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ArrayPushOpConfig
Section titled “ArrayPushOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ArraySetOpConfig
Section titled “ArraySetOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
AssetRef
Section titled “AssetRef”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
AuditLogEntry
Section titled “AuditLogEntry”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
AuditLogProvider
Section titled “AuditLogProvider”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
AuditLogQuery
Section titled “AuditLogQuery”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
AuthRuntimePeer
Section titled “AuthRuntimePeer”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
AuthUserAccessDecision
Section titled “AuthUserAccessDecision”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
AuthUserAccessInput
Section titled “AuthUserAccessInput”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
BatchOpConfig
Section titled “BatchOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
BeforeInvokeArgs
Section titled “BeforeInvokeArgs”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
CaptchaConfig
Section titled “CaptchaConfig”Supported CAPTCHA verification providers.
'recaptcha'— Google reCAPTCHA v2 or v3'hcaptcha'— hCaptcha'turnstile'— Cloudflare Turnstile
Source: packages/slingshot-core/src/captcha.ts
ChannelForwardConfig
Section titled “ChannelForwardConfig”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
ChannelIncomingEventDeclaration
Section titled “ChannelIncomingEventDeclaration”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
ChannelPermissionConfig
Section titled “ChannelPermissionConfig”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
ChannelReceiveConfig
Section titled “ChannelReceiveConfig”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
CollectionOpConfig
Section titled “CollectionOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ComputedAggregateOpConfig
Section titled “ComputedAggregateOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ComputedField
Section titled “ComputedField”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ConfigDefinition
Section titled “ConfigDefinition”Typed, env-validated app config — the canonical answer to “where does this setting come from and what shape must it have?”
Slingshot already has a secret-resolution layer (SecretRepository)
that answers “where does this VALUE come from” (env var, AWS SSM, Vault,
etc.). defineConfig answers the orthogonal question “what SHAPE does this
app require, and where do those typed fields live in env.” Most apps need
both; they’re complementary.
A config definition declares a namespace and a Zod schema. At app boot,
the framework reads process.env (or a custom source), maps each schema
field to a NAMESPACE_FIELD env var, validates the whole thing through Zod,
and caches the result. After boot, anywhere in your app, cfg.get() returns
the typed validated values — fail-fast at startup, not at the first request.
Source: packages/slingshot-core/src/config.ts
ConsumeOpConfig
Section titled “ConsumeOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ContactData
Section titled “ContactData”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
CoreAuthAdapter
Section titled “CoreAuthAdapter”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
CounterSnapshotEntry
Section titled “CounterSnapshotEntry”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
Source: packages/slingshot-core/src/metrics.ts
CreateEventPublisherOptions
Section titled “CreateEventPublisherOptions”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
CronRegistryRepository
Section titled “CronRegistryRepository”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
CsrfConfig
Section titled “CsrfConfig”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
CursorPaginationOptions
Section titled “CursorPaginationOptions”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
CursorParamDefaults
Section titled “CursorParamDefaults”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
CustomOpConfig
Section titled “CustomOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
DataEncryptionKey
Section titled “DataEncryptionKey”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.
Source: packages/slingshot-core/src/crypto.ts
DefaultValidationErrorBody
Section titled “DefaultValidationErrorBody”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
DefinePackageInput
Section titled “DefinePackageInput”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
DeliveryAdapter
Section titled “DeliveryAdapter”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
DeriveOpConfig
Section titled “DeriveOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
DeriveSource
Section titled “DeriveSource”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
DomainRouteDefinition
Section titled “DomainRouteDefinition”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
DynamicEventBus
Section titled “DynamicEventBus”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
EmbedData
Section titled “EmbedData”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
EmbedsPeer
Section titled “EmbedsPeer”Cross-package handle to the embeds plugin’s URL unfurling capability.
Source: packages/slingshot-core/src/embedsPeer.ts
EnterpriseAdapter
Section titled “EnterpriseAdapter”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
EntityAdapter
Section titled “EntityAdapter”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityAdapterLookup
Section titled “EntityAdapterLookup”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
EntityChannelConfig
Section titled “EntityChannelConfig”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
EntityChannelDeclaration
Section titled “EntityChannelDeclaration”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
EntityConfig
Section titled “EntityConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityDtoConfig
Section titled “EntityDtoConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityPaginatedResult
Section titled “EntityPaginatedResult”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityPermissionConfig
Section titled “EntityPermissionConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
EntityRegistry
Section titled “EntityRegistry”General-purpose entity registry.
Plugins that need to discover entities at runtime (search indexing, schema generation, admin UIs, migration tooling, documentation) use this registry.
Created by the framework during bootstrap, exposed to plugin lifecycle hooks
on SlingshotFrameworkConfig, and consumed by framework-owned services such as
search indexing.
Source: packages/slingshot-core/src/entityRegistry.ts
EntityRouteConfig
Section titled “EntityRouteConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
EntityRouteDataScopeConfig
Section titled “EntityRouteDataScopeConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
EntityRoutePolicyConfig
Section titled “EntityRoutePolicyConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
EntitySearchConfig
Section titled “EntitySearchConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityStorageConventions
Section titled “EntityStorageConventions”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityStorageFieldMap
Section titled “EntityStorageFieldMap”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityStorageHints
Section titled “EntityStorageHints”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntitySystemFields
Section titled “EntitySystemFields”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityTtlConfig
Section titled “EntityTtlConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
ErrorDisposition
Section titled “ErrorDisposition”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
EvaluationScope
Section titled “EvaluationScope”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
EventBusSerializationOptions
Section titled “EventBusSerializationOptions”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
EventDefinition
Section titled “EventDefinition”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventDefinitionRegistry
Section titled “EventDefinitionRegistry”Registry of EventDefinitions keyed by event name, freezable once all plugins have registered their events.
Source: packages/slingshot-core/src/eventDefinitionRegistry.ts
EventDefinitionRegistryOptions
Section titled “EventDefinitionRegistryOptions”Registry of EventDefinitions keyed by event name, freezable once all plugins have registered their events.
Source: packages/slingshot-core/src/eventDefinitionRegistry.ts
EventEnvelope
Section titled “EventEnvelope”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventEnvelopeMeta
Section titled “EventEnvelopeMeta”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventPublishContext
Section titled “EventPublishContext”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventSchemaRegistry
Section titled “EventSchemaRegistry”Result of validating an event payload against a registered schema.
Source: packages/slingshot-core/src/eventSchemaRegistry.ts
EventScope
Section titled “EventScope”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventSerializer
Section titled “EventSerializer”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
EventSubscriptionPrincipal
Section titled “EventSubscriptionPrincipal”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
ExistsOpConfig
Section titled “ExistsOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FieldDef
Section titled “FieldDef”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
FieldOptions
Section titled “FieldOptions”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
FieldTypeMap
Section titled “FieldTypeMap”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
FieldUpdateOpConfig
Section titled “FieldUpdateOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterContains
Section titled “FilterContains”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterGt
Section titled “FilterGt”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterGte
Section titled “FilterGte”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterIn
Section titled “FilterIn”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterLt
Section titled “FilterLt”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterLte
Section titled “FilterLte”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterNe
Section titled “FilterNe”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterNin
Section titled “FilterNin”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FunctionsHooks
Section titled “FunctionsHooks”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
FunctionsRuntime
Section titled “FunctionsRuntime”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
FunctionsRuntimeConfig
Section titled “FunctionsRuntimeConfig”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
GaugeSnapshotEntry
Section titled “GaugeSnapshotEntry”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
Source: packages/slingshot-core/src/metrics.ts
GenerateOptions
Section titled “GenerateOptions”Public API for generating fake data from any Zod schema.
Source: packages/slingshot-core/src/faker/generateFromSchema.ts
GeoSearchConfig
Section titled “GeoSearchConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
GroupByConfig
Section titled “GroupByConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
GroupMembershipRecord
Section titled “GroupMembershipRecord”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
GroupRecord
Section titled “GroupRecord”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
GroupResolver
Section titled “GroupResolver”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
GroupsAdapter
Section titled “GroupsAdapter”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
HandlerArgs
Section titled “HandlerArgs”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
HandlerConfig
Section titled “HandlerConfig”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
HandlerMeta
Section titled “HandlerMeta”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
HealthAppConfig
Section titled “HealthAppConfig”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HealthCheck
Section titled “HealthCheck”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HealthIndicator
Section titled “HealthIndicator”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HealthIndicatorContext
Section titled “HealthIndicatorContext”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HealthIndicatorResult
Section titled “HealthIndicatorResult”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HealthReport
Section titled “HealthReport”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HookServices
Section titled “HookServices”HookServices — typed accessors for out-of-request callbacks.
Auth lifecycle hooks, orchestration workflow hooks, and queue dead-letter callbacks
fire outside any Hono request context — there is no c to read state from. Without
a canonical contract these callbacks ended up starved differently in each plugin
(some got pluginState, others got only request metadata, others nothing at all).
HookServices is the shared shape every plugin’s out-of-request callbacks intersect
into their payload. Hook authors get the same typed accessors that
PackageDomainRouteContext exposes to package-authored route handlers, so the
ergonomics line up across request and non-request callsites:
postLogin: async ({ userId, services }) => {const adapter = services.entities.get(GuestIdentity); // typed via entity moduleconst mailer = services.capabilities.require(MailerCapability);await services.bus.emit('user.signed-in', { userId });}Plugins build a HookServices instance by calling buildHookServices() at the call
site of each hook, threading their own pluginState/bus/logger and the app’s
Hono reference. The framework supplies the shared
SlingshotContext.capabilityProviders map so capability lookups work identically to
those inside request handlers.
Worker-process boundary. Some adapters (notably the Temporal orchestration worker)
run hook code in a separate process where the framework’s app is not reachable.
Those callsites pass services: undefined rather than fabricate broken accessors.
Hook authors who need framework state from worker-mode code should restructure their
work to run at the workflow level (in-process) and thread data into the task input.
Source: packages/slingshot-core/src/hookServices.ts
IdempotencyAdapter
Section titled “IdempotencyAdapter”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
IdempotencyOpts
Section titled “IdempotencyOpts”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
IdentityProfile
Section titled “IdentityProfile”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
IdentityResolver
Section titled “IdentityResolver”Actor-based identity abstraction.
Decouples all framework consumers (guards, permissions, data scoping, audit,
entity routes) from specific auth-provider field names by mapping them into
the canonical Actor shape.
Custom auth integrations implement IdentityResolver to map their own
identity representation into the canonical Actor shape.
Source: packages/slingshot-core/src/identity.ts
IdentityResolverInput
Section titled “IdentityResolverInput”Actor-based identity abstraction.
Decouples all framework consumers (guards, permissions, data scoping, audit,
entity routes) from specific auth-provider field names by mapping them into
the canonical Actor shape.
Custom auth integrations implement IdentityResolver to map their own
identity representation into the canonical Actor shape.
Source: packages/slingshot-core/src/identity.ts
IncrementOpConfig
Section titled “IncrementOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
IndexDef
Section titled “IndexDef”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
InProcessMetricsEmitter
Section titled “InProcessMetricsEmitter”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
Source: packages/slingshot-core/src/metrics.ts
InvokeAbort
Section titled “InvokeAbort”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
InvokeOpts
Section titled “InvokeOpts”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
KafkaConnectorDropStats
Section titled “KafkaConnectorDropStats”Health snapshot for one inbound Kafka connector.
Source: packages/slingshot-core/src/kafkaConnectors.ts
KafkaConnectorHandle
Section titled “KafkaConnectorHandle”Health snapshot for one inbound Kafka connector.
Source: packages/slingshot-core/src/kafkaConnectors.ts
KafkaConnectorHealth
Section titled “KafkaConnectorHealth”Health snapshot for one inbound Kafka connector.
Source: packages/slingshot-core/src/kafkaConnectors.ts
KafkaInboundConnectorHealth
Section titled “KafkaInboundConnectorHealth”Health snapshot for one inbound Kafka connector.
Source: packages/slingshot-core/src/kafkaConnectors.ts
KafkaOutboundConnectorHealth
Section titled “KafkaOutboundConnectorHealth”Health snapshot for one inbound Kafka connector.
Source: packages/slingshot-core/src/kafkaConnectors.ts
ListUsersInput
Section titled “ListUsersInput”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
ListUsersResult
Section titled “ListUsersResult”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
LocationData
Section titled “LocationData”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
LogFields
Section titled “LogFields”Structured logger contract used by prod-track packages.
The interface is deliberately small: four severity methods plus child()
for fields that should appear on every log line in a sub-component (request
id, plugin name, queue id, etc.). Implementations must never throw — log
sinks that crash the caller are worse than silent loss.
createConsoleLogger is the default — one JSON line per call written to the
underlying console method matching the level. noopLogger is the test
default for code paths that need a logger handle but no output.
Source: packages/slingshot-core/src/observability/logger.ts
Logger
Section titled “Logger”Structured logger contract used by prod-track packages.
The interface is deliberately small: four severity methods plus child()
for fields that should appear on every log line in a sub-component (request
id, plugin name, queue id, etc.). Implementations must never throw — log
sinks that crash the caller are worse than silent loss.
createConsoleLogger is the default — one JSON line per call written to the
underlying console method matching the level. noopLogger is the test
default for code paths that need a logger handle but no output.
Source: packages/slingshot-core/src/observability/logger.ts
LookupOpConfig
Section titled “LookupOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
M2MClientRecord
Section titled “M2MClientRecord”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
MailRenderer
Section titled “MailRenderer”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
ManagedUserCapabilities
Section titled “ManagedUserCapabilities”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
ManagedUserProvider
Section titled “ManagedUserProvider”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
ManagedUserRecord
Section titled “ManagedUserRecord”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
ManagedUserScope
Section titled “ManagedUserScope”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
MetricsEmitter
Section titled “MetricsEmitter”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
Source: packages/slingshot-core/src/metrics.ts
MetricsSnapshot
Section titled “MetricsSnapshot”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
Source: packages/slingshot-core/src/metrics.ts
MfaAdapter
Section titled “MfaAdapter”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
NotificationBuilder
Section titled “NotificationBuilder”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
NotificationCreatedEventPayload
Section titled “NotificationCreatedEventPayload”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
NotificationRecord
Section titled “NotificationRecord”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
NotifyInput
Section titled “NotifyInput”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
NotifyManyInput
Section titled “NotifyManyInput”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
OAuthAdapter
Section titled “OAuthAdapter”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
OffsetParamDefaults
Section titled “OffsetParamDefaults”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
OnErrorArgs
Section titled “OnErrorArgs”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
OperationIdempotencyAdapter
Section titled “OperationIdempotencyAdapter”Operation-level idempotency contract used by delivery and retry-aware packages (mail, push, notifications, orchestration) to dedup retried operations.
Remarks: This is distinct from the HTTP IdempotencyAdapter contract in ../idempotencyAdapter.ts, which is dedicated to the request-replay middleware (caching the full HTTP response for a given Idempotency-Key header).
Remarks: The contract here is keyed on a structured IdempotencyKey and stores an arbitrary payload (typed at the call site). Callers wrap their operation in withIdempotency so that retries skip work and replay the prior result.
Source: packages/slingshot-core/src/idempotency/index.ts
PackageCapabilityHandle
Section titled “PackageCapabilityHandle”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageCapabilityProviderContext
Section titled “PackageCapabilityProviderContext”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageCapabilityReader
Section titled “PackageCapabilityReader”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageContract
Section titled “PackageContract”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageContractMetadata
Section titled “PackageContractMetadata”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageDomainRouteContext
Section titled “PackageDomainRouteContext”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageEntityReader
Section titled “PackageEntityReader”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageEntityRef
Section titled “PackageEntityRef”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageInspection
Section titled “PackageInspection”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PackageRouteRequestContext
Section titled “PackageRouteRequestContext”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PaginatedResult
Section titled “PaginatedResult”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
PaginationConfig
Section titled “PaginationConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
PaginationOptions
Section titled “PaginationOptions”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
ParsedBody
Section titled “ParsedBody”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
ParsedContent
Section titled “ParsedContent”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
ParsedCursorParams
Section titled “ParsedCursorParams”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
ParsedOffsetParams
Section titled “ParsedOffsetParams”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
PermissionEvaluator
Section titled “PermissionEvaluator”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
PermissionGrant
Section titled “PermissionGrant”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
PermissionRegistry
Section titled “PermissionRegistry”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
PermissionsAdapter
Section titled “PermissionsAdapter”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
PermissionsState
Section titled “PermissionsState”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
PipeOpConfig
Section titled “PipeOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
PipeStep
Section titled “PipeStep”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
PluginSeedContext
Section titled “PluginSeedContext”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
PluginSetupContext
Section titled “PluginSetupContext”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
PluginStateCarrier
Section titled “PluginStateCarrier”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
PluginStateKey
Section titled “PluginStateKey”Writable plugin state used internally by the framework bootstrap lifecycle.
Source: packages/slingshot-core/src/pluginState.ts
PolicyDecision
Section titled “PolicyDecision”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
PolicyInput
Section titled “PolicyInput”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
PolicyToken
Section titled “PolicyToken”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
PolicyTokenRef
Section titled “PolicyTokenRef”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
PostgresBundle
Section titled “PostgresBundle”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
PostgresHealthCheckResult
Section titled “PostgresHealthCheckResult”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
Source: packages/slingshot-core/src/postgresRuntime.ts
PostgresPoolRuntime
Section titled “PostgresPoolRuntime”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
Source: packages/slingshot-core/src/postgresRuntime.ts
PostgresPoolStatsSnapshot
Section titled “PostgresPoolStatsSnapshot”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
Source: packages/slingshot-core/src/postgresRuntime.ts
PublicEntityBuilder
Section titled “PublicEntityBuilder”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PublicEntityCandidate
Section titled “PublicEntityCandidate”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PublicEntityExposureMetadata
Section titled “PublicEntityExposureMetadata”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PublishedCapabilityRecord
Section titled “PublishedCapabilityRecord”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PublishedEntityRecord
Section titled “PublishedEntityRecord”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PublishedInteractionsPeer
Section titled “PublishedInteractionsPeer”Cross-package handle for resolving and updating interactive message components published by a peer package.
Source: packages/slingshot-core/src/publishedInteractionsPeer.ts
PublishedPackageCapability
Section titled “PublishedPackageCapability”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PushFormatterPeer
Section titled “PushFormatterPeer”Shape of a formatted push notification: title plus optional body, data, icon, badge, and URL.
Source: packages/slingshot-core/src/pushPeer.ts
PushMessageLike
Section titled “PushMessageLike”Shape of a formatted push notification: title plus optional body, data, icon, badge, and URL.
Source: packages/slingshot-core/src/pushPeer.ts
QueueLifecycle
Section titled “QueueLifecycle”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
QuotePreview
Section titled “QuotePreview”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
RecordErrorArgs
Section titled “RecordErrorArgs”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
RecordOutcome
Section titled “RecordOutcome”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
RedisLike
Section titled “RedisLike”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
RelationDef
Section titled “RelationDef”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
RenderResult
Section titled “RenderResult”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
RequestScope
Section titled “RequestScope”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
Source: packages/slingshot-core/src/requestScope.ts
RequestScopeContext
Section titled “RequestScopeContext”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
Source: packages/slingshot-core/src/requestScope.ts
RequestScopeStore
Section titled “RequestScopeStore”Request-scoped state — the canonical way to wire per-request resources.
A request scope is a typed handle for “something that exists for the duration of a single HTTP request and gets cleaned up at the end.” Common examples: a database transaction, a per-request HTTP client with the actor’s token, an idempotency session, a request-bound tracing helper.
The framework runs factory lazily on first getRequestScoped(c, scope)
inside a request and caches the result for the rest of that request. After
the handler returns (success or error), the framework calls cleanup for
every scope that was actually initialized — in LIFO order, so a transaction
can roll back before its underlying connection is released.
Source: packages/slingshot-core/src/requestScope.ts
ResolvedEntityConfig
Section titled “ResolvedEntityConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
ResolvedEntityStorageConventions
Section titled “ResolvedEntityStorageConventions”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
ResolvedEntityStorageFieldMap
Section titled “ResolvedEntityStorageFieldMap”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
ResolvedEntitySystemFields
Section titled “ResolvedEntitySystemFields”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
ResolvedOperations
Section titled “ResolvedOperations”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ResolvedPersistence
Section titled “ResolvedPersistence”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
ResolvedPreference
Section titled “ResolvedPreference”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
ResolvedStores
Section titled “ResolvedStores”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
ResourceTypeDefinition
Section titled “ResourceTypeDefinition”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
RolesAdapter
Section titled “RolesAdapter”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
RoomPersistenceConfig
Section titled “RoomPersistenceConfig”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
RouteCascadeConfig
Section titled “RouteCascadeConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteEventConfig
Section titled “RouteEventConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteIdempotencyConfig
Section titled “RouteIdempotencyConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteNamedOperationConfig
Section titled “RouteNamedOperationConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteOperationConfig
Section titled “RouteOperationConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RoutePermissionConfig
Section titled “RoutePermissionConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouterAdapterOptions
Section titled “RouterAdapterOptions”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
RouteRateLimitConfig
Section titled “RouteRateLimitConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteRetentionConfig
Section titled “RouteRetentionConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteWebhookConfig
Section titled “RouteWebhookConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RuntimeFs
Section titled “RuntimeFs”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
RuntimeGlob
Section titled “RuntimeGlob”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
RuntimePassword
Section titled “RuntimePassword”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
RuntimeServerFactory
Section titled “RuntimeServerFactory”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
RuntimeServerInstance
Section titled “RuntimeServerInstance”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
RuntimeServerOptions
Section titled “RuntimeServerOptions”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
RuntimeSqliteDatabase
Section titled “RuntimeSqliteDatabase”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
RuntimeSqlitePreparedStatement
Section titled “RuntimeSqlitePreparedStatement”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
RuntimeSqliteRunResult
Section titled “RuntimeSqliteRunResult”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
RuntimeSqliteStatement
Section titled “RuntimeSqliteStatement”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
RuntimeWebSocket
Section titled “RuntimeWebSocket”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
RuntimeWebSocketHandler
Section titled “RuntimeWebSocketHandler”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
SafeFetchOptions
Section titled “SafeFetchOptions”Minimal local type for the subset of the undici Dispatcher we use. We
keep this local so callers do not need to import undici types directly.
Source: packages/slingshot-core/src/http/safeFetch.ts
SearchClientLike
Section titled “SearchClientLike”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
Source: packages/slingshot-core/src/searchPluginRuntime.ts
SearchFieldConfig
Section titled “SearchFieldConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
SearchOpConfig
Section titled “SearchOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
SearchPluginRuntime
Section titled “SearchPluginRuntime”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
Source: packages/slingshot-core/src/searchPluginRuntime.ts
SearchProviderContract
Section titled “SearchProviderContract”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
SearchQueryLike
Section titled “SearchQueryLike”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
Source: packages/slingshot-core/src/searchPluginRuntime.ts
SearchResponseLike
Section titled “SearchResponseLike”Search plugin runtime contract.
Defines the shape stored in pluginState by slingshot-search and consumed
by framework-internal code (createContextStoreInfra) for write-through
sync and late entity initialization.
Lives in slingshot-core because both sides (framework and search plugin)
depend on core — same rationale as SearchProviderContract.
Source: packages/slingshot-core/src/searchPluginRuntime.ts
SecretDefinition
Section titled “SecretDefinition”Secret repository contracts — read-only abstraction for resolving credentials, API keys, and signing secrets from any backing store.
Resolved at startup BEFORE database connections are established. Implementations must be self-contained (no DB dependencies).
Source: packages/slingshot-core/src/secrets.ts
SecretRepository
Section titled “SecretRepository”Secret repository contracts — read-only abstraction for resolving credentials, API keys, and signing secrets from any backing store.
Resolved at startup BEFORE database connections are established. Implementations must be self-contained (no DB dependencies).
Source: packages/slingshot-core/src/secrets.ts
SessionRecord
Section titled “SessionRecord”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
SigningConfig
Section titled “SigningConfig”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
SlingshotContext
Section titled “SlingshotContext”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
SlingshotEventBus
Section titled “SlingshotEventBus”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
SlingshotEventMap
Section titled “SlingshotEventMap”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
SlingshotEvents
Section titled “SlingshotEvents”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
SlingshotFrameworkConfig
Section titled “SlingshotFrameworkConfig”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
SlingshotHandler
Section titled “SlingshotHandler”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
SlingshotPackageDefinition
Section titled “SlingshotPackageDefinition”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
SlingshotPackageDomainModule
Section titled “SlingshotPackageDomainModule”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
SlingshotPackageEntityModuleLike
Section titled “SlingshotPackageEntityModuleLike”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
SlingshotPlugin
Section titled “SlingshotPlugin”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
SlingshotResolvedConfig
Section titled “SlingshotResolvedConfig”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
SlingshotRuntime
Section titled “SlingshotRuntime”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
SseEndpointConfig
Section titled “SseEndpointConfig”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
StandalonePlugin
Section titled “StandalonePlugin”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
StorageAdapter
Section titled “StorageAdapter”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
StoredMessage
Section titled “StoredMessage”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
StoreInfra
Section titled “StoreInfra”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
SubjectRef
Section titled “SubjectRef”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
SubscriptionOpts
Section titled “SubscriptionOpts”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
SuspendUserInput
Section titled “SuspendUserInput”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
SuspensionAdapter
Section titled “SuspensionAdapter”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
SystemEventData
Section titled “SystemEventData”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
TenantConfig
Section titled “TenantConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
TenantScopedOpts
Section titled “TenantScopedOpts”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
TestablePermissionsAdapter
Section titled “TestablePermissionsAdapter”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
TimingSnapshotEntry
Section titled “TimingSnapshotEntry”Unified metrics emitter contract.
Thin, dependency-free interface that prod-track packages call to record counters, gauges, and timings without coupling to a specific backend (Prometheus, OpenTelemetry, etc). Defaults to a no-op so packages can emit unconditionally and let the host application decide whether and where to collect.
This is a separate seam from the framework-owned MetricsState
(Prometheus-style registry used by the built-in /metrics HTTP endpoint).
Plugins should prefer this MetricsEmitter for ad-hoc operational signals;
the framework metrics plugin remains the home for the request-level
counters/histograms exposed at the scrape endpoint.
Source: packages/slingshot-core/src/metrics.ts
TransactionOpConfig
Section titled “TransactionOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
TransactionStep
Section titled “TransactionStep”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
TransitionOpConfig
Section titled “TransitionOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
TriggerAdapter
Section titled “TriggerAdapter”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
TriggerExtractedMeta
Section titled “TriggerExtractedMeta”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
TriggerOpts
Section titled “TriggerOpts”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
TriggerRecord
Section titled “TriggerRecord”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
TypedRouteContext
Section titled “TypedRouteContext”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
TypedRouteRequestSpec
Section titled “TypedRouteRequestSpec”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
TypedRouteRespond
Section titled “TypedRouteRespond”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
TypedRouteResponseSpec
Section titled “TypedRouteResponseSpec”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
TypedRouteValidation
Section titled “TypedRouteValidation”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
UnsuspendUserInput
Section titled “UnsuspendUserInput”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
UpdateUserInput
Section titled “UpdateUserInput”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
UploadRecord
Section titled “UploadRecord”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
UploadRegistryRepository
Section titled “UploadRegistryRepository”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
UploadResult
Section titled “UploadResult”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
UploadRuntimeState
Section titled “UploadRuntimeState”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
UpsertOpConfig
Section titled “UpsertOpConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
UserQuery
Section titled “UserQuery”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
UserRecord
Section titled “UserRecord”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
ValidationErrorDetail
Section titled “ValidationErrorDetail”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
VoiceMetadata
Section titled “VoiceMetadata”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
WebAuthnAdapter
Section titled “WebAuthnAdapter”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
WebAuthnCredential
Section titled “WebAuthnCredential”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
WithIdempotencyOptions
Section titled “WithIdempotencyOptions”Operation-level idempotency contract used by delivery and retry-aware packages (mail, push, notifications, orchestration) to dedup retried operations.
Remarks: This is distinct from the HTTP IdempotencyAdapter contract in ../idempotencyAdapter.ts, which is dedicated to the request-replay middleware (caching the full HTTP response for a given Idempotency-Key header).
Remarks: The contract here is keyed on a structured IdempotencyKey and stores an arbitrary payload (typed at the call site). Callers wrap their operation in withIdempotency so that retries skip work and replay the prior result.
Source: packages/slingshot-core/src/idempotency/index.ts
WsMessageDefaults
Section titled “WsMessageDefaults”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
WsMessageRepository
Section titled “WsMessageRepository”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
WsPluginEndpoint
Section titled “WsPluginEndpoint”Shared WebSocket utility helpers.
Extracted to slingshot-core so both the framework (src/framework/lib/ws.ts)
and entity packages (slingshot-entity) can import without creating a
cross-layer dependency.
Source: packages/slingshot-core/src/wsHelpers.ts
WsRateLimitBucket
Section titled “WsRateLimitBucket”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
WsRateLimitConfig
Section titled “WsRateLimitConfig”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
WsRecoveryConfig
Section titled “WsRecoveryConfig”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
WsSessionEntry
Section titled “WsSessionEntry”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
WsState
Section titled “WsState”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
WsTransportHandle
Section titled “WsTransportHandle”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
ActorKind
Section titled “ActorKind”Actor-based identity abstraction.
Decouples all framework consumers (guards, permissions, data scoping, audit,
entity routes) from specific auth-provider field names by mapping them into
the canonical Actor shape.
Custom auth integrations implement IdentityResolver to map their own
identity representation into the canonical Actor shape.
Source: packages/slingshot-core/src/identity.ts
AfterHook
Section titled “AfterHook”Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
AggregateMethod
Section titled “AggregateMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
AppEnv
Section titled “AppEnv”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
AppVariables
Section titled “AppVariables”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
ArrayPullMethod
Section titled “ArrayPullMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ArrayPushMethod
Section titled “ArrayPushMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ArraySetMethod
Section titled “ArraySetMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
AuthAdapter
Section titled “AuthAdapter”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
AutoDefault
Section titled “AutoDefault”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
BatchMethod
Section titled “BatchMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
CacheAdapter
Section titled “CacheAdapter”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
CacheStoreName
Section titled “CacheStoreName”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
CaptchaProvider
Section titled “CaptchaProvider”Supported CAPTCHA verification providers.
'recaptcha'— Google reCAPTCHA v2 or v3'hcaptcha'— hCaptcha'turnstile'— Cloudflare Turnstile
Source: packages/slingshot-core/src/captcha.ts
ChannelAuthConfig
Section titled “ChannelAuthConfig”Authentication strategy enforced at WebSocket channel subscribe time.
'userAuth'— requires a valid session (resolved byRequestActorResolver)'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
CollectionMethod
Section titled “CollectionMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
CollectionOperation
Section titled “CollectionOperation”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ComputedAggregateMethod
Section titled “ComputedAggregateMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ComputeSpec
Section titled “ComputeSpec”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ConfigSource
Section titled “ConfigSource”Typed, env-validated app config — the canonical answer to “where does this setting come from and what shape must it have?”
Slingshot already has a secret-resolution layer (SecretRepository)
that answers “where does this VALUE come from” (env var, AWS SSM, Vault,
etc.). defineConfig answers the orthogonal question “what SHAPE does this
app require, and where do those typed fields live in env.” Most apps need
both; they’re complementary.
A config definition declares a namespace and a Zod schema. At app boot,
the framework reads process.env (or a custom source), maps each schema
field to a NAMESPACE_FIELD env var, validates the whole thing through Zod,
and caches the result. After boot, anywhere in your app, cfg.get() returns
the typed validated values — fail-fast at startup, not at the first request.
Source: packages/slingshot-core/src/config.ts
ConsumeBooleanMethod
Section titled “ConsumeBooleanMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ConsumeEntityMethod
Section titled “ConsumeEntityMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ContentFormat
Section titled “ContentFormat”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
ContentSegment
Section titled “ContentSegment”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
ContractDefinePackageInput
Section titled “ContractDefinePackageInput”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
CoreRegistrar
Section titled “CoreRegistrar”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
CoreRegistrarSnapshot
Section titled “CoreRegistrarSnapshot”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
CustomAutoDefaultResolver
Section titled “CustomAutoDefaultResolver”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
CustomOnUpdateResolver
Section titled “CustomOnUpdateResolver”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
DateTruncation
Section titled “DateTruncation”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
DeriveMethod
Section titled “DeriveMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
EmailTemplate
Section titled “EmailTemplate”A static email template (subject/html/text) registered by a plugin and consumed by the mail plugin.
Source: packages/slingshot-core/src/emailTemplates.ts
EntityChannelConfigInput
Section titled “EntityChannelConfigInput”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
EntityDataScopedCrudOp
Section titled “EntityDataScopedCrudOp”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
EntityDtoMapper
Section titled “EntityDtoMapper”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
EntityRouteConfigInput
Section titled “EntityRouteConfigInput”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
EntityRouteDataScopeSource
Section titled “EntityRouteDataScopeSource”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
ErrorKind
Section titled “ErrorKind”One normalized record extracted from a trigger event.
Source: packages/slingshot-core/src/functions.ts
EventExposure
Section titled “EventExposure”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventKey
Section titled “EventKey”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
EventValidationResult
Section titled “EventValidationResult”Result of validating an event payload against a registered schema.
Source: packages/slingshot-core/src/eventSchemaRegistry.ts
ExistsMethod
Section titled “ExistsMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FieldType
Section titled “FieldType”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
FieldUpdateMethod
Section titled “FieldUpdateMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterExpression
Section titled “FilterExpression”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterOperator
Section titled “FilterOperator”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FilterValue
Section titled “FilterValue”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
FingerprintBuilder
Section titled “FingerprintBuilder”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
GrantEffect
Section titled “GrantEffect”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
Resolve the canonical Actor from a HandlerMeta object.
Source: packages/slingshot-core/src/handler.ts
HealthIndicatorSeverity
Section titled “HealthIndicatorSeverity”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
HealthState
Section titled “HealthState”Component health contract for prod-track packages.
Components (event bus adapters, queues, search clients, mailers, etc.)
implement HealthCheck so the framework can aggregate per-component
state into a single readiness/liveness response without each package
inventing its own shape.
getHealth() is synchronous and returns the last cached state — cheap
enough to call from a /health request handler. checkHealth() is the
optional active probe that may perform I/O against the underlying system.
Source: packages/slingshot-core/src/observability/health.ts
IdempotencyKey
Section titled “IdempotencyKey”Operation-level idempotency contract used by delivery and retry-aware packages (mail, push, notifications, orchestration) to dedup retried operations.
Remarks: This is distinct from the HTTP IdempotencyAdapter contract in ../idempotencyAdapter.ts, which is dedicated to the request-replay middleware (caching the full HTTP response for a given Idempotency-Key header).
Remarks: The contract here is keyed on a structured IdempotencyKey and stores an arbitrary payload (typed at the call site). Callers wrap their operation in withIdempotency so that retries skip work and replay the prior result.
Source: packages/slingshot-core/src/idempotency/index.ts
IncrementMethod
Section titled “IncrementMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
InferCreateInput
Section titled “InferCreateInput”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
InferEntity
Section titled “InferEntity”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
InferFieldType
Section titled “InferFieldType”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
InferOperationMethods
Section titled “InferOperationMethods”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
InferUpdateInput
Section titled “InferUpdateInput”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
LogLevel
Section titled “LogLevel”Structured logger contract used by prod-track packages.
The interface is deliberately small: four severity methods plus child()
for fields that should appear on every log line in a sub-component (request
id, plugin name, queue id, etc.). Implementations must never throw — log
sinks that crash the caller are worse than silent loss.
createConsoleLogger is the default — one JSON line per call written to the
underlying console method matching the level. noopLogger is the test
default for code paths that need a logger handle but no output.
Source: packages/slingshot-core/src/observability/logger.ts
LookupManyMethod
Section titled “LookupManyMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
MergeStrategy
Section titled “MergeStrategy”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
NamedOpHttpMethod
Section titled “NamedOpHttpMethod”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
NotificationPriority
Section titled “NotificationPriority”Shared notification record / adapter / builder types used across packages.
These types form the typed surface that slingshot-notifications publishes through
its Notifications package contract (@lastshotlabs/slingshot-notifications/public.ts).
Cross-package consumers resolve the contract handles via ctx.capabilities.require(...)
— the legacy NOTIFICATIONS_PLUGIN_STATE_KEY peer-state publish has been removed.
Source: packages/slingshot-core/src/notificationsPeer.ts
OperationConfig
Section titled “OperationConfig”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
PackageStability
Section titled “PackageStability”Maturity label for a Slingshot package, driving the runtime warning emitted for non-stable packages.
Source: packages/slingshot-core/src/stability.ts
PipeMethod
Section titled “PipeMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
PluginStateMap
Section titled “PluginStateMap”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
PolicyAction
Section titled “PolicyAction”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
PolicyResolver
Section titled “PolicyResolver”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
PostAuthGuard
Section titled “PostAuthGuard”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
PostAuthGuardFailure
Section titled “PostAuthGuardFailure”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
PostgresMigrationMode
Section titled “PostgresMigrationMode”Whether the Postgres runtime applies migrations on startup or assumes the schema is already migrated.
Source: packages/slingshot-core/src/postgresRuntime.ts
PublicEntityExposureMode
Section titled “PublicEntityExposureMode”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
PushFormatterPeerFn
Section titled “PushFormatterPeerFn”Shape of a formatted push notification: title plus optional body, data, icon, badge, and URL.
Source: packages/slingshot-core/src/pushPeer.ts
RateLimitAdapter
Section titled “RateLimitAdapter”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
RepoFactories
Section titled “RepoFactories”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
RequestActorResolver
Section titled “RequestActorResolver”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
ResolvedSecrets
Section titled “ResolvedSecrets”Secret repository contracts — read-only abstraction for resolving credentials, API keys, and signing secrets from any backing store.
Resolved at startup BEFORE database connections are established. Implementations must be self-contained (no DB dependencies).
Source: packages/slingshot-core/src/secrets.ts
RouteAuthConfig
Section titled “RouteAuthConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteAuthRegistry
Section titled “RouteAuthRegistry”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
RouteIdempotencyScope
Section titled “RouteIdempotencyScope”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
RouteKey
Section titled “RouteKey”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
RouteMiddlewareConfig
Section titled “RouteMiddlewareConfig”Authentication strategy for a route or operation.
'userAuth'— requires a valid session cookie or user token (viaRouteAuthRegistry.userAuth)'bearer'— requires a bearer token (viaRouteAuthRegistry.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
SearchArrayMethod
Section titled “SearchArrayMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
SearchPaginatedMethod
Section titled “SearchPaginatedMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
SecretSchema
Section titled “SecretSchema”Secret repository contracts — read-only abstraction for resolving credentials, API keys, and signing secrets from any backing store.
Resolved at startup BEFORE database connections are established. Implementations must be self-contained (no DB dependencies).
Source: packages/slingshot-core/src/secrets.ts
SecretStoreType
Section titled “SecretStoreType”Secret repository contracts — read-only abstraction for resolving credentials, API keys, and signing secrets from any backing store.
Resolved at startup BEFORE database connections are established. Implementations must be self-contained (no DB dependencies).
Source: packages/slingshot-core/src/secrets.ts
SecurityEventKey
Section titled “SecurityEventKey”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
SlingshotPackageModule
Section titled “SlingshotPackageModule”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
SoftDeleteConfig
Section titled “SoftDeleteConfig”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
SseClientData
Section titled “SseClientData”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
SseFilter
Section titled “SseFilter”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
StoreType
Section titled “StoreType”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
SubjectType
Section titled “SubjectType”The type of entity a permission grant applies to.
'user'— a concrete end-user identity;subjectIdis 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 viaGroupResolver;subjectIdis the group’s ID; grants to a group apply to all current members'service-account'— a non-human M2M client or API service identity;subjectIdis 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
TestableRepoFactories
Section titled “TestableRepoFactories”Canonical store infrastructure contract shared across all slingshot packages.
Plugin authors import these types from @lastshotlabs/slingshot-core to declare
repository factories without depending on framework or auth internals.
The pattern:
- Declare
RepoFactories<YourRepo>with one factory per StoreType - Call
resolveRepo(factories, storeType, infra)at startup - The framework provides
StoreInfra— your factory receives it
Framework injection symbols
Section titled “Framework injection symbols”The framework bootstrap (createContextStoreInfra) injects additional
capabilities onto StoreInfra via well-known Reflect symbols. Packages
that need these capabilities use Reflect.get(infra, SYMBOL) — they never
receive these as function arguments (CLAUDE.md Rule 16).
RESOLVE_ENTITY_FACTORIES — injected by the bootstrap with the
createEntityFactories function. Allows packages/slingshot-entity to create
RepoFactories<T> from entity configs without importing from the root app.
RESOLVE_COMPOSITE_FACTORIES — injected by the bootstrap with the
createCompositeFactories function. Used by the composite entity path in
packages/slingshot-entity to build multi-entity adapter sets.
Source: packages/slingshot-core/src/storeInfra.ts
TransactionMethod
Section titled “TransactionMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
TransitionBooleanMethod
Section titled “TransitionBooleanMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
TransitionEntityMethod
Section titled “TransitionEntityMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
`TS infers
Section titled “`TS infers”// a return type that points at slingshot-core/dist/src/operations and
// raises TS2742.
LookupOneMethod`
Source: packages/slingshot-core/src/operations.ts
TypedRouteInput
Section titled “TypedRouteInput”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
TypedRouteResponses
Section titled “TypedRouteResponses”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts
UpsertMethod
Section titled “UpsertMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
UpsertWithCreatedFlagMethod
Section titled “UpsertWithCreatedFlagMethod”Operation configuration types — canonical definitions.
12 declarative operation patterns + 1 custom escape hatch.
Both the codegen package (slingshot-data) and the runtime framework import from here.
Single source of truth — never duplicate these types in consumer packages.
Remarks: Operation configs are consumed by: - slingshot-data code generators to produce typed adapter implementations - The runtime framework’s op.* executor registry for live evaluation - InferOperationMethods<Ops, Entity> for TypeScript adapter method typing
Source: packages/slingshot-core/src/operations.ts
ValidationErrorFormatter
Section titled “ValidationErrorFormatter”A single field-level validation error detail produced by the default formatter.
Source: packages/slingshot-core/src/context.ts
ValidationMode
Section titled “ValidationMode”Union of all registered event names — the string keys of the SlingshotEventMap.
Source: packages/slingshot-core/src/eventTypes.ts
WsPublishFn
Section titled “WsPublishFn”Shared WebSocket utility helpers.
Extracted to slingshot-core so both the framework (src/framework/lib/ws.ts)
and entity packages (slingshot-entity) can import without creating a
cross-layer dependency.
Source: packages/slingshot-core/src/wsHelpers.ts
Exports
Section titled “Exports”defineEntity
Section titled “defineEntity”Config-driven entity & repository generation.
Plugin authors describe an entity’s shape declaratively using the field.*() builder
API, then get generated TypeScript types, Zod schemas, adapter interfaces, and
backend-specific implementations from a single source of truth.
import { defineEntity, field, index } from '@lastshotlabs/slingshot-core';
export const Message = defineEntity('Message', {namespace: 'chat',fields: {id: field.string({ primary: true, default: 'uuid' }),roomId: field.string(),authorId: field.string(),content: field.string(),type: field.enum(['text', 'image', 'system'], { default: 'text' }),metadata: field.json({ optional: true }),createdAt: field.date({ default: 'now' }),updatedAt: field.date({ default: 'now', onUpdate: 'now' }),},softDelete: { field: 'status', value: 'deleted' },defaultSort: { field: 'createdAt', direction: 'desc' },pagination: { cursor: { fields: ['createdAt', 'id'] }, defaultLimit: 50, maxLimit: 200 },indexes: [index(['roomId', 'createdAt'], { direction: 'desc' }),index(['authorId', 'createdAt'], { direction: 'desc' }),],});Source: packages/slingshot-core/src/entityConfig.ts
domain
Section titled “domain”Typed, named token a package publishes and consumers resolve to exchange a capability value across packages.
Source: packages/slingshot-core/src/packageAuthoring.ts