@lastshotlabs/slingshot-permissions
npm install @lastshotlabs/slingshot-permissions
Functions
Section titled “Functions”createAuthGroupResolver
Section titled “createAuthGroupResolver”Creates a GroupResolver backed by a Slingshot auth runtime when one is available.
The returned resolver is lazy: it reads the current runtime on each call so it can be
created before the auth plugin has populated pluginState. When auth is unavailable or
the adapter does not implement group lookups, the resolver returns an empty set.
function createAuthGroupResolver(getRuntime: () => AuthLikeRuntime | null | undefined,): GroupResolverSource: packages/slingshot-permissions/src/lib/authGroupResolver.ts
createEvaluationCache
Section titled “createEvaluationCache”Create an in-memory evaluation cache with the given TTL.
function createEvaluationCache(options?: EvaluationCacheOptions): EvaluationCacheSource: packages/slingshot-permissions/src/lib/evaluationCache.ts
createMemoryAuditTrailStore
Section titled “createMemoryAuditTrailStore”Create an in-memory audit trail store.
Data is lost on process restart. Suitable for development, testing, and low-traffic single-process deployments.
function createMemoryAuditTrailStore(options?: MemoryAuditTrailStoreOptions,): AuditTrailStoreSource: packages/slingshot-permissions/src/lib/auditTrail.ts
createMemoryPermissionsAdapter
Section titled “createMemoryPermissionsAdapter”Creates an in-memory PermissionsAdapter for development and testing.
Grants are stored in a plain array; no external dependencies required. All query methods respect active-only filtering (revoked and expired grants excluded). Scope cascade (global -> tenant -> resource-type -> resource) is applied in memory.
Remarks: Prints a startup warning to console.warn. Not suitable for production - all data is lost on process restart.
function createMemoryPermissionsAdapter(options?: { maxEntries?: number; }): PermissionsMemoryAdapterSource: packages/slingshot-permissions/src/adapters/memory.ts
createMongoPermissionsAdapter
Section titled “createMongoPermissionsAdapter”Creates a MongoDB-backed PermissionsAdapter using a Mongoose connection.
Registers a PermissionGrant model on the provided connection. UUID strings are used
as _id values (not ObjectIds). Indexes are declared in the schema for
(subjectType, subjectId), (resourceType, resourceId), and tenantId.
function createMongoPermissionsAdapter(conn: MongoConnectionLike): PermissionsMongoAdapterSource: packages/slingshot-permissions/src/adapters/mongo.ts
createPermissionEvaluator
Section titled “createPermissionEvaluator”Creates a PermissionEvaluator that resolves whether a subject can perform an action.
The evaluator implements a deny-wins cascade model:
- Collect all active grants for the subject (and their groups if
groupResolveris set). - Apply scope matching — global → tenant → resource-type → specific resource.
- If any deny grant covers the action, return
falseimmediately. - If any allow grant covers the action, return
true. - Default-deny: return
false.
function createPermissionEvaluator(config: EvaluatorConfig): EvaluatorWithHealthSource: packages/slingshot-permissions/src/lib/evaluator.ts
createPermissionRegistry
Section titled “createPermissionRegistry”Creates an in-memory PermissionRegistry for registering resource type definitions.
The registry maps resource types (e.g. 'posts', 'admin:billing') to their allowed
roles and the actions each role grants. Once registered, a resource type is immutable —
re-registration throws to enforce clean domain ownership.
The super-admin role (SUPER_ADMIN_ROLE) always returns ['*'] for any resource type,
regardless of what is registered.
function createPermissionRegistry(): PermissionRegistrySource: packages/slingshot-permissions/src/lib/registry.ts
createPermissionsPackage
Section titled “createPermissionsPackage”Creates the slingshot-permissions package.
Resolves the permissions adapter from the active store type during
setupMiddleware and stores a frozen PermissionsState
({ evaluator, registry, adapter }) in ctx.pluginState under the
package capabilities slot. Packages that require permissions (e.g.
slingshot-community, slingshot-content) declare 'slingshot-permissions'
as a dependency and read the shared state from pluginState (or resolve via
ctx.capabilities.require(PermissionsEvaluatorCap)) instead of
constructing their own instances.
Group expansion is disabled by default. To resolve user → group membership
from slingshot-auth, pass a groupResolver factory via config.
Registration order: declare this package before any consumer package so the
framework’s topological sort places its setupMiddleware first.
function createPermissionsPackage(rawConfig?: PermissionsPluginConfig,): SlingshotPackageDefinitionSource: packages/slingshot-permissions/src/plugin.ts
createPermissionsPostgresAdapter
Section titled “createPermissionsPostgresAdapter”Creates a PostgreSQL-backed PermissionsAdapter.
Accepts any PoolLike (a pg.Pool or compatible mock). Schema migrations run automatically
using a separate _permission_schema_version table via a locked client transaction
guarded by a configurable timeout. Roles are stored as JSONB.
The returned adapter includes a healthCheck() method that performs a SELECT 1
probe against the pool, useful for observability endpoints and plugin-level health
aggregation.
async function createPermissionsPostgresAdapter(pool: PoolLike, options?: CreatePermissionsPostgresAdapterOptions,): Promise< PermissionsPostgresAdapter &Source: packages/slingshot-permissions/src/adapters/postgres.ts
createSqlitePermissionsAdapter
Section titled “createSqlitePermissionsAdapter”Creates a SQLite-backed PermissionsAdapter using a RuntimeSqliteDatabase.
Schema migrations run automatically on first call. WAL mode and foreign-key enforcement are enabled. Roles are stored as JSON text in a single column.
function createSqlitePermissionsAdapter(db: RuntimeSqliteDatabase,): PermissionsSqliteAdapterSource: packages/slingshot-permissions/src/adapters/sqlite.ts
Permissions
Section titled “Permissions”Provider-owned package contract for slingshot-permissions.
Source: packages/slingshot-permissions/src/public.ts
PermissionsAdapterCap
Section titled “PermissionsAdapterCap”Capability handle for the persistence adapter that backs grant storage.
Source: packages/slingshot-permissions/src/public.ts
permissionsAdapterFactories
Section titled “permissionsAdapterFactories”Pre-built PermissionsAdapterFactories covering all supported store types.
Pass this to your framework’s adapter resolution call to automatically select the
correct permissions backend based on the configured storeType.
Source: packages/slingshot-permissions/src/factories.ts
PermissionsEvaluatorCap
Section titled “PermissionsEvaluatorCap”Capability handle for the permission evaluator (answers can() queries).
Source: packages/slingshot-permissions/src/public.ts
PermissionsHealthCap
Section titled “PermissionsHealthCap”Capability for reading the aggregated permissions health snapshot.
Consumers resolve via ctx.capabilities.require(PermissionsHealthCap)() and
receive a PermissionsHealth representing adapter, evaluator, and
adapter-level connectivity state at call time.
Source: packages/slingshot-permissions/src/public.ts
PermissionsRegistryCap
Section titled “PermissionsRegistryCap”Capability handle for the permission registry (resource-type → role/action mappings).
Source: packages/slingshot-permissions/src/public.ts
seedSuperAdmin
Section titled “seedSuperAdmin”Seeds a super-admin grant for the given subject using the SUPER_ADMIN_ROLE.
The grant is global (no tenant, no resource) so it applies everywhere. This function is idempotent — if the subject already holds an active super-admin grant it returns that grant’s ID without creating a duplicate. Safe to call on every deployment.
async function seedSuperAdmin(adapter: PermissionsAdapter, opts: { subjectId: string; subjectType?: SubjectType; grantedBy?: string },): Promise<string>Source: packages/slingshot-permissions/src/lib/bootstrap.ts
SUPER_ADMIN_ROLE
Section titled “SUPER_ADMIN_ROLE”The magic role name that bypasses all permission checks.
Any subject with this role in their effective grants is allowed to perform any action on any resource without the evaluator consulting the registry. Grant this role with extreme caution.
Source: packages/slingshot-core/src/permissions.ts
validateGrant
Section titled “validateGrant”Validate a permission grant before it is persisted.
Enforces the following rules:
resourceIdrequiresresourceTypeto be non-null- At least one role must be specified
effectmust be'allow'or'deny'expiresAt, when provided, must be aDatein the futuresubjectTypemust be one of'user' | 'group' | 'service-account'
function validateGrant(grant: Omit<PermissionGrant, 'id' | 'grantedAt'>): voidSource: packages/slingshot-core/src/permissions.ts
withAuditTrail
Section titled “withAuditTrail”Wrap a PermissionsAdapter so that every mutation method records an audit
trail entry before performing the operation.
The wrapped adapter’s mutation methods are transparently proxied — callers interact with it exactly as they would the bare adapter.
function withAuditTrail(adapter: PermissionsAdapter, store: AuditTrailStore, options?: WithAuditTrailOptions,): PermissionsAdapterSource: packages/slingshot-permissions/src/lib/auditTrail.ts
Classes
Section titled “Classes”PermissionQueryTimeoutError
Section titled “PermissionQueryTimeoutError”Structured error thrown when an adapter query exceeds queryTimeoutMs.
Carries adapter, scope, and subjectId context so operators can identify
which call timed out without parsing log strings.
Source: packages/slingshot-permissions/src/lib/evaluator.ts
PermissionsAdapterError
Section titled “PermissionsAdapterError”Thrown when a permissions adapter cannot be resolved or fails an adapter operation.
Source: packages/slingshot-permissions/src/errors.ts
PermissionsConfigError
Section titled “PermissionsConfigError”Thrown when permissions plugin configuration is invalid or unsupported.
Source: packages/slingshot-permissions/src/errors.ts
PermissionsError
Section titled “PermissionsError”Base error class for all permissions-related errors.
Carries a machine-readable code for programmatic discrimination at catch sites.
Source: packages/slingshot-permissions/src/errors.ts
Interfaces
Section titled “Interfaces”AuditTrailEntry
Section titled “AuditTrailEntry”A single audit trail entry recording one permission change.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
AuditTrailFilter
Section titled “AuditTrailFilter”Filter for querying audit trail entries.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
AuditTrailStore
Section titled “AuditTrailStore”Persistent store for audit trail entries.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
CreatePermissionsPostgresAdapterOptions
Section titled “CreatePermissionsPostgresAdapterOptions”Options accepted by createPermissionsPostgresAdapter.
Source: packages/slingshot-permissions/src/adapters/postgres.ts
EvaluationCache
Section titled “EvaluationCache”TTL-based evaluation cache.
Thread-safe in the sense that JavaScript’s event loop serialises Map access. Not safe across multiple processes or host machines — each runtime instance maintains its own in-memory cache.
Source: packages/slingshot-permissions/src/lib/evaluationCache.ts
EvaluationCacheEntry
Section titled “EvaluationCacheEntry”A single entry in the evaluation cache.
Source: packages/slingshot-permissions/src/lib/evaluationCache.ts
EvaluationCacheOptions
Section titled “EvaluationCacheOptions”Options for createEvaluationCache.
Source: packages/slingshot-permissions/src/lib/evaluationCache.ts
EvaluatorHealth
Section titled “EvaluatorHealth”Health snapshot describing the evaluator’s recent error and timeout activity.
Cross-package consumers should read this snapshot through PermissionsHealthCap
rather than calling getHealth() directly; the capability is the canonical
public surface and the local getHealth() is what the package uses to
populate it.
All fields are cumulative counters since evaluator creation; consumers track deltas to compute rates if needed.
Source: packages/slingshot-permissions/src/lib/evaluator.ts
EvaluatorLogger
Section titled “EvaluatorLogger”Minimal logger interface used by the evaluator for structured warn/error output.
Defaults to console. Inject a custom logger (e.g. pino, bunyan, slog) to capture
evaluator diagnostics in your application’s structured logging pipeline.
Source: packages/slingshot-permissions/src/lib/evaluator.ts
EvaluatorWithHealth
Section titled “EvaluatorWithHealth”Evaluator augmented with a getHealth() snapshot accessor.
Source: packages/slingshot-permissions/src/lib/evaluator.ts
GroupExpansionFailure
Section titled “GroupExpansionFailure”One element of the failure list passed to onGroupExpansionError.
Source: packages/slingshot-permissions/src/lib/evaluator.ts
GroupResolver
Section titled “GroupResolver”Resolves the group memberships for a user.
Provided to the permissions evaluator so group-based grants can be expanded
into per-user effective grants without the evaluator depending on the
GroupsAdapter directly.
Source: packages/slingshot-core/src/permissions.ts
MemoryAuditTrailStoreOptions
Section titled “MemoryAuditTrailStoreOptions”Options for createMemoryAuditTrailStore.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
PermissionEvaluator
Section titled “PermissionEvaluator”High-level permission evaluator that answers can(subject, action, scope) queries.
The evaluator fetches effective grants for the subject (expanding group memberships via
GroupResolver), resolves the actions granted by each role using PermissionRegistry,
and applies deny-wins semantics.
Source: packages/slingshot-core/src/permissions.ts
PermissionGrant
Section titled “PermissionGrant”A single row in the permissions store — a durable record that a subject holds (or is denied) specific roles on a resource or scope.
Remarks: Grants cascade through four levels of specificity: 1. Global (tenantId=null, resourceType=null, resourceId=null) 2. Tenant-wide (tenantId=T, resourceType=null, resourceId=null) 3. Type-wide (tenantId=T, resourceType=RT, resourceId=null) 4. Specific resource (tenantId=T, resourceType=RT, resourceId=RID)
Remarks: Deny effects at any level override allows from any other level.
Source: packages/slingshot-core/src/permissions.ts
PermissionRegistry
Section titled “PermissionRegistry”In-memory registry that maps resource types to their role/action definitions.
Created once per app instance during bootstrap. Plugins register their resource
types during setupPost. The permissions evaluator queries this registry when
resolving can() checks.
Source: packages/slingshot-core/src/permissions.ts
PermissionsAdapter
Section titled “PermissionsAdapter”Storage adapter for the slingshot-permissions plugin.
Implementations are responsible for persisting PermissionGrant records
and answering effective-grant queries. A grant is “effective” when:
- It has not been revoked (
revokedAtis null/undefined) - It has not expired (
expiresAtis null or in the future) - Its stored scope is satisfied by the evaluation scope
Remarks: Follow the swappable provider pattern: add a new implementation file and a case in the factory dispatch — never modify this interface for adapter-specific needs.
Source: packages/slingshot-core/src/permissions.ts
PermissionsHealth
Section titled “PermissionsHealth”Aggregated health snapshot for slingshot-permissions. Returned by the
PermissionsHealthCap capability.
status is derived from the underlying signals:
'unhealthy'when no permissions adapter has been resolved yet (the package hasn’t completedsetupMiddleware, or another package pre-seeded state without an adapter).'degraded'when the evaluator has observed any query timeouts or group-expansion errors since startup, or when the backing adapter reports a disconnected state.'healthy'otherwise.
Source: packages/slingshot-permissions/src/public.ts
PermissionsPluginConfig
Section titled “PermissionsPluginConfig”Configuration for the permissions package.
Controls the backing adapter, optional group expansion, and evaluator limits used when resolving role grants for user, group, and service-account subjects.
Source: packages/slingshot-permissions/src/plugin.ts
PermissionsPostgresAdapterHealth
Section titled “PermissionsPostgresAdapterHealth”Adapter-level health payload returned by healthCheck() on the Postgres
permissions adapter.
Source: packages/slingshot-permissions/src/adapters/postgres.ts
ResourceTypeDefinition
Section titled “ResourceTypeDefinition”Declares the roles and actions available for a single resource type.
Plugins call PermissionRegistry.register() during setupPost to declare which
actions exist and which roles imply which actions. The evaluator uses this to resolve
can(subject, action, scope) queries.
Source: packages/slingshot-core/src/permissions.ts
SubjectRef
Section titled “SubjectRef”A reference to the subject of a permission grant (who the grant applies to).
Source: packages/slingshot-core/src/permissions.ts
TestablePermissionsAdapter
Section titled “TestablePermissionsAdapter”A PermissionsAdapter that adds a clear() method for test isolation.
Implement this interface in test-only adapters to reset state between test cases.
Source: packages/slingshot-core/src/permissions.ts
WithAuditTrailOptions
Section titled “WithAuditTrailOptions”Options for withAuditTrail.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
AuditAction
Section titled “AuditAction”The action that was performed on the resource.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
AuditResourceType
Section titled “AuditResourceType”The kind of resource that was changed.
Currently only 'grant' is recorded by the built-in adapters. The type is
a union string to allow future extension without a breaking change.
Source: packages/slingshot-permissions/src/lib/auditTrail.ts
GrantEffect
Section titled “GrantEffect”Whether the grant allows or denies the specified roles on a resource.
Remarks: Deny wins: when the evaluator collects effective grants for a subject (including group-expanded grants), any 'deny' grant that covers the requested action causes can() to return false — regardless of how many 'allow' grants also apply. This holds across all cascade levels: a specific-resource deny overrides a global allow, and a global deny overrides a specific-resource allow.
Source: packages/slingshot-core/src/permissions.ts
PermissionsAdapterFactories
Section titled “PermissionsAdapterFactories”A record that maps every StoreType to a factory function producing a
PermissionsAdapter from StoreInfra. Pass to the framework’s adapter resolution
machinery so the correct backend is selected at startup.
Remarks: redis is rejected because there is no Redis permissions adapter.
Source: packages/slingshot-permissions/src/factories.ts
PermissionsMongoAdapter
Section titled “PermissionsMongoAdapter”Alias for TestablePermissionsAdapter returned by createMongoPermissionsAdapter.
Exposes the clear() method for resetting state in integration tests.
Source: packages/slingshot-permissions/src/adapters/mongo.ts
PermissionsPostgresAdapter
Section titled “PermissionsPostgresAdapter”Alias for TestablePermissionsAdapter returned by createPermissionsPostgresAdapter.
Exposes the clear() method for resetting state in integration tests.
Source: packages/slingshot-permissions/src/adapters/postgres.ts
PermissionsSqliteAdapter
Section titled “PermissionsSqliteAdapter”Alias for TestablePermissionsAdapter returned by createSqlitePermissionsAdapter.
Exposes the clear() method for resetting state between tests.
Source: packages/slingshot-permissions/src/adapters/sqlite.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