@test137e29b/auth
v2.0.1
Published
Authentication, permissions, and request-context utilities for Node.js services
Maintainers
Readme
@test137e29b/auth
Enterprise authentication, permissions, and context utilities shared across the platform. The package ships distinct entry points for browser clients, shared/common helpers, and server-side context construction so consumers can pull in just the surface they need.
Contents
- Installation
- Package Structure
- Usage Examples
- Development Workflow
- Coding Standards
- Testing & Coverage
- Releasing
- License
Installation
npm install @test137e29b/auth
# or
yarn add @test137e29b/authNode.js >= 22.14.0 is required; use nvm use 22 (or equivalent) before running scripts.
Package Structure
Client APIs (@test137e29b/auth/client)
The client bundle is currently a placeholder that exports no runtime symbols. It exists so consuming applications can start wiring imports without pulling server-only code. Future browser-centric helpers (JWT parsing, lightweight policy checks) should live here.
Common APIs (@test137e29b/auth/common)
Shared helpers that are safe to consume from both browser and server environments.
jwt/— branded JWT token builders and runtime guards for each authentication surface.policy/— permission policy compilation utilities (CompiledPolicy, matching helpers, type definitions).
Permission Naming Conventions
Policies follow a <service>.<resource>.<action> naming convention in practice, but the matcher accepts any number of discrete segments. Examples:
merchant.orders.viewservice.admin.*
Wildcards operate per segment:
- A trailing
*(service.resource.*) matches any action beneath a specific resource. - A mid-segment wildcard (
service.*.read) matches any resource but still requires an explicit action suffix. - A global wildcard (
*) matches everything and should only appear in deny lists or tightly controlled scopes.
Segments must be non-empty; partial wildcards such as serv*ice are rejected at parse time. Rules with additional segments (for example service.orders.refund.issue) remain valid.
Example
import { CompiledPolicy } from '@test137e29b/auth/common';
const policy = CompiledPolicy.build(
['merchant.orders.view', 'merchant.orders.update'],
['merchant.orders.delete']
);
policy.isAllowed('merchant.orders.view'); // true
policy.isAllowed('merchant.orders.delete'); // false (explicit deny wins)
const decision = policy.explain('merchant.orders.update');
// { decision: 'allow', reason: 'allow', matchedAllow: 'merchant.orders.update' }Server APIs (@test137e29b/auth/server)
The server bundle re-exports both the request context utilities and the NestJS integration helpers, so import the members you need directly.
- Request contexts:
BaseContextsubclasses (PublicContext,ServiceContext, etc.),getBaseContextOptions, and API-version helpers. - Nest integration:
Contextdecorator,createAddContextMiddleware,PolicyGuard, and related types/constants.
Example: Creating a request context
import { CompiledPolicy } from '@test137e29b/auth/common';
import { PublicContext } from '@test137e29b/auth/server';
import type { ApiVersion } from '@test137e29b/auth/server';
const permissions = CompiledPolicy.build(['service.orders.view'], []);
const baseOptions = {
apiVersion: 'v1' as ApiVersion,
appId: 'app-123',
permissions
};
const publicContext = new PublicContext(baseOptions);
publicContext.getSentryContext();
// { requestId: '<generated>', apiVersion: 'v1', appId: 'app-123', type: 'public' }NestJS Platform Support
The package supports both NestJS Express and NestJS Fastify platforms. Choose your platform and follow the corresponding guide:
- Express Integration Guide — For NestJS applications using Express (default)
- Fastify Integration Guide — For NestJS applications using Fastify
Both platforms share identical middleware logic with only adapter differences:
- Middleware Creation: Use
createAddContextMiddleware(Express) orcreateAddContextMiddlewareFastify(Fastify) - Dependencies: Both
expressandfastifyare optional peer dependencies—install only what you need - Controllers: Use the same
@Context()decorator and context types regardless of platform
Example: Nest middleware
import { Context, EContextType, ServiceContext, isServiceContext } from '@test137e29b/auth/server';
import type { RequestContext } from '@test137e29b/auth/server';
@Controller()
export class DemoController {
@Get('/health')
ping(@Context() ctx: RequestContext) {
const { requestId, apiVersion } = ctx;
return { ok: true, requestId, apiVersion };
}
@Get('/service-only')
list(@Context(isServiceContext) ctx: ServiceContext) {
return { ok: true, requestId: ctx.requestId };
}
}Example: Registering the context middleware (Express)
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { createAddContextMiddleware } from '@test137e29b/auth/server';
// For Fastify, use: import { createAddContextMiddlewareFastify } from '@test137e29b/auth/server';
const addContext = createAddContextMiddleware({
// defaultPolicy applies to unauthenticated requests and authenticated users without roles
defaultPolicy: { allow: ['public.health.check'], deny: [] },
bearer: {
jwksUri: 'https://auth.example.com/.well-known/bearer-jwks.json',
issuer: 'https://auth.example.com',
audience: 'test137e29b-api'
},
service: {
tokens: ['svc-secret-token'],
policy: { allow: ['service.internal.*'], deny: [] }
},
device: {
jwksUri: 'https://auth.example.com/.well-known/device-jwks.json'
},
sentry: {
enabled: true
},
getRolePolicy: async roleId => fetchRolePolicy(roleId)
});
@Module({})
export class ApiModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(addContext).forRoutes('*');
}
}
async function fetchRolePolicy(roleId: string) {
// Retrieve allow/deny arrays from your auth service.
return { allow: ['merchant.orders.view'], deny: [] };
}Tip: All runtime exports and types are surfaced from the top-level entry points (
@test137e29b/auth/common,@test137e29b/auth/server, etc.); you never need to import from nested paths such as@test137e29b/auth/server/context/apiVersion.
Usage Examples
- Policy explanation:
CompiledPolicy.explain()returns the allow/deny decision, matched rules, and reason codes so caller logs can be richer. - Context logging:
BaseContextexposestoLoggable()andgetSentryContext(); downstream contexts (developer, service, organisation, etc.) enrich these with domain-specific metadata. - API version handling:
normaliseApiVersion()canonicalises incoming headers and falls back toDEFAULT_API_VERSION.
Refer to tests/unit/context for practical, isolated examples of context behaviour.
Development Workflow
- Install dependencies with
npm install. - Run
npm testduring development; usenpm test -- --coverageto verify code coverage before shipping. - Format and lint with
npm run lint(runs Prettier and ESLint). - Build distributables via
npm run prepublishOnly(clearsdist/and compiles withtsc). - Security checks run through
npm run audit-dependencies.
Local Tooling
- Node
>=22.14.0, npm 10+. - Jest for unit tests (configured via
package.json). - TypeScript 5.5.
Coding Standards
- Follow existing folder-driven export structure (
common,client,server). Do not import fromsrc/libsdirectly in consumers. - Prefer the error helper classes in
src/libs/errors.ts(e.g.BadRequestError,InternalError) instead of instantiatingBaseErrordirectly. - Keep type guards pure and side-effect free; accept
anyinputs to compose with reusable helper combinators. - Context classes should always pass a permissions list into
BaseContextand attach Bunyan-compatible loggers viagetLogger().child({ requestId }). - Add succinct comments only when logic is non-obvious; rely on descriptive names otherwise.
- Tests live under
tests/unit/**, mirroring the runtime directory where practical.
Testing & Coverage
npm test # run unit tests
npm test -- --coverage # run tests with coverage reportingRecent coverage targets: ≥85% statements, ≥65% branches for core modules (libs, server/context). Run coverage before merges to avoid regressions.
Releasing
- Ensure
npm run prepublishOnlysucceeds. - Verify
package.jsonexport map only exposes supported entry points (common,client,server). - Tag releases following semver (e.g.
v0.2.0). Internal projects consume via private registry mirror. - Publish with an authenticated session (
NPM_TOKEN) so the scoped package remains private (access: restricted).
License
© test137E29B. All rights reserved. Internal use only. Redistribution outside test137E29B requires written permission.
