Skip to content

@lastshotlabs/slingshot-permissions

npm install @lastshotlabs/slingshot-permissions

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,): GroupResolver

Source: packages/slingshot-permissions/src/lib/authGroupResolver.ts

Create an in-memory evaluation cache with the given TTL.

function createEvaluationCache(options?: EvaluationCacheOptions): EvaluationCache

Source: packages/slingshot-permissions/src/lib/evaluationCache.ts

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,): AuditTrailStore

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

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; }): PermissionsMemoryAdapter

Source: packages/slingshot-permissions/src/adapters/memory.ts

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): PermissionsMongoAdapter

Source: packages/slingshot-permissions/src/adapters/mongo.ts

Creates a PermissionEvaluator that resolves whether a subject can perform an action.

The evaluator implements a deny-wins cascade model:

  1. Collect all active grants for the subject (and their groups if groupResolver is set).
  2. Apply scope matching — global → tenant → resource-type → specific resource.
  3. If any deny grant covers the action, return false immediately.
  4. If any allow grant covers the action, return true.
  5. Default-deny: return false.
function createPermissionEvaluator(config: EvaluatorConfig): EvaluatorWithHealth

Source: packages/slingshot-permissions/src/lib/evaluator.ts

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(): PermissionRegistry

Source: packages/slingshot-permissions/src/lib/registry.ts

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,): SlingshotPackageDefinition

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

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

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,): PermissionsSqliteAdapter

Source: packages/slingshot-permissions/src/adapters/sqlite.ts

Provider-owned package contract for slingshot-permissions.

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

Capability handle for the persistence adapter that backs grant storage.

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

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

Capability handle for the permission evaluator (answers can() queries).

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

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

Capability handle for the permission registry (resource-type → role/action mappings).

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

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

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

Validate a permission grant before it is persisted.

Enforces the following rules:

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

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

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,): PermissionsAdapter

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

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

Thrown when a permissions adapter cannot be resolved or fails an adapter operation.

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

Thrown when permissions plugin configuration is invalid or unsupported.

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

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

A single audit trail entry recording one permission change.

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

Filter for querying audit trail entries.

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

Persistent store for audit trail entries.

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

Options accepted by createPermissionsPostgresAdapter.

Source: packages/slingshot-permissions/src/adapters/postgres.ts

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

A single entry in the evaluation cache.

Source: packages/slingshot-permissions/src/lib/evaluationCache.ts

Options for createEvaluationCache.

Source: packages/slingshot-permissions/src/lib/evaluationCache.ts

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

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

Evaluator augmented with a getHealth() snapshot accessor.

Source: packages/slingshot-permissions/src/lib/evaluator.ts

One element of the failure list passed to onGroupExpansionError.

Source: packages/slingshot-permissions/src/lib/evaluator.ts

Resolves the group memberships for a user.

Provided to the permissions evaluator so group-based grants can be expanded into per-user effective grants without the evaluator depending on the GroupsAdapter directly.

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

Options for createMemoryAuditTrailStore.

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

High-level permission evaluator that answers can(subject, action, scope) queries.

The evaluator fetches effective grants for the subject (expanding group memberships via GroupResolver), resolves the actions granted by each role using PermissionRegistry, and applies deny-wins semantics.

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

A single row in the permissions store — a durable record that a subject holds (or is denied) specific roles on a resource or scope.

Remarks: Grants cascade through four levels of specificity: 1. Global (tenantId=null, resourceType=null, resourceId=null) 2. Tenant-wide (tenantId=T, resourceType=null, resourceId=null) 3. Type-wide (tenantId=T, resourceType=RT, resourceId=null) 4. Specific resource (tenantId=T, resourceType=RT, resourceId=RID)

Remarks: Deny effects at any level override allows from any other level.

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

In-memory registry that maps resource types to their role/action definitions.

Created once per app instance during bootstrap. Plugins register their resource types during setupPost. The permissions evaluator queries this registry when resolving can() checks.

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

Storage adapter for the slingshot-permissions plugin.

Implementations are responsible for persisting PermissionGrant records and answering effective-grant queries. A grant is “effective” when:

  • It has not been revoked (revokedAt is null/undefined)
  • It has not expired (expiresAt is null or in the future)
  • Its stored scope is satisfied by the evaluation scope

Remarks: Follow the swappable provider pattern: add a new implementation file and a case in the factory dispatch — never modify this interface for adapter-specific needs.

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

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 completed setupMiddleware, 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

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

Adapter-level health payload returned by healthCheck() on the Postgres permissions adapter.

Source: packages/slingshot-permissions/src/adapters/postgres.ts

Declares the roles and actions available for a single resource type.

Plugins call PermissionRegistry.register() during setupPost to declare which actions exist and which roles imply which actions. The evaluator uses this to resolve can(subject, action, scope) queries.

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

A reference to the subject of a permission grant (who the grant applies to).

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

A PermissionsAdapter that adds a clear() method for test isolation. Implement this interface in test-only adapters to reset state between test cases.

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

Options for withAuditTrail.

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

The action that was performed on the resource.

Source: packages/slingshot-permissions/src/lib/auditTrail.ts

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

Whether the grant allows or denies the specified roles on a resource.

Remarks: Deny wins: when the evaluator collects effective grants for a subject (including group-expanded grants), any 'deny' grant that covers the requested action causes can() to return false — regardless of how many 'allow' grants also apply. This holds across all cascade levels: a specific-resource deny overrides a global allow, and a global deny overrides a specific-resource allow.

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

A 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

Alias for TestablePermissionsAdapter returned by createMongoPermissionsAdapter. Exposes the clear() method for resetting state in integration tests.

Source: packages/slingshot-permissions/src/adapters/mongo.ts

Alias for TestablePermissionsAdapter returned by createPermissionsPostgresAdapter. Exposes the clear() method for resetting state in integration tests.

Source: packages/slingshot-permissions/src/adapters/postgres.ts

Alias for TestablePermissionsAdapter returned by createSqlitePermissionsAdapter. Exposes the clear() method for resetting state between tests.

Source: packages/slingshot-permissions/src/adapters/sqlite.ts

The type of entity a permission grant applies to.

  • 'user' — a concrete end-user identity; subjectId is the user’s primary key as stored in the auth adapter (e.g. a UUID or nanoid)
  • 'group' — a named collection of users resolved at evaluation time via GroupResolver; subjectId is the group’s ID; grants to a group apply to all current members
  • 'service-account' — a non-human M2M client or API service identity; subjectId is the service account’s client ID or name; used for backend-to-backend trust grants that should not be confused with end-user permissions

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