01
Sessions are storage-agnostic
createSession accepts an application-provided SessionStore and issues opaque cookies with Secure, HttpOnly, SameSite=Lax, and Path=/ defaults. It does not supply a user database, OAuth/OIDC flow, password verifier, or hosted login.
- Store only the opaque session identifier in the cookie.
- Use durable session storage for multiple processes or instances.
- Rotate, expire, revoke, and audit sessions through application-owned services.
02
Authorize at the resource boundary
Use requireRole or requirePermission for coarse policy and requireAccess for tenant, ownership, or ABAC rules. A cookie or hidden client field does not prove ownership or permission; the Action or server boundary that owns the resource must enforce the decision.
03
Compose Node middleware deliberately
Use createMiddleware and composeMiddleware for cross-cutting Node request work such as request identifiers, session resolution, rate limits, headers, and private-prefix guards. Middleware must call next() at most once. On Deno or Cloudflare, compose equivalent Fetch handlers instead of importing Node middleware.
import { createSession, requireAccess, requirePermission } from '@mohammedaydan/security'
import { composeMiddleware, createMiddleware } from '@mohammedaydan/serve'
const sessions = createSession(sessionStore)
export async function approveInvoice(request: Request, invoice: Invoice) {
const { principal } = await sessions.require(request)
requirePermission(principal, 'invoice:approve')
await requireAccess(principal, invoice, (actor, resource) =>
actor.tenantId === resource.tenantId,
)
}
export const handler = composeMiddleware(
requestIdMiddleware,
sessionMiddleware,
createMiddleware('./dist/client'),
)PRACTICAL LABS
Run this capability.
Each example states the observable output, the boundary that remains your responsibility, and the check that proves the result.
01
Authorize the actual resource
TypeScriptimport { createSession, requireAccess, requirePermission } from '@mohammedaydan/security'
const sessions = createSession(applicationSessionStore)
const { principal } = await sessions.require(request)
requirePermission(principal, 'article:write')
await requireAccess(principal, article, (user, resource) => user.tenantId === resource.tenantId)- OUTPUT
- An Action can resolve an opaque session then apply a permission and application resource rule.
- BOUNDARY
- Nexis does not supply your identity provider, session persistence, password flow, or audit backend.
- PROVE IT
- Test missing, expired, revoked, denied-permission, and wrong-tenant paths.
VERIFICATION
Prove the contract.
Test missing, expired, and revoked sessions; denied roles and permissions; tenant and ownership mismatches; middleware ordering; and the invariant that a rejected Action never reaches its mutation handler.