Anarchitecture Bricks Docs

Repository documentation hub for packages, guides, and generated references.

@anarchitects/auth-ts

Public HTTP authority belongs to anarchitecture-contracts under ADR-0016. This implementation pins @anarchitects/auth-contracts@0.1.0 and derives its transitional TypeBox DTO exports from that published canonical graph. Domain models remain local. Nest keeps its Fastify validation and serialization adapter; Angular keeps the existing DTO imports. See the adoption evidence and TS Contracts Guide for scope and limits.

TypeScript consumers must use package-export-aware resolution (NodeNext, Node16 where supported by their module graph, or bundler). Legacy node10 resolution cannot resolve the canonical packages. Runtime ESM and CommonJS entry points remain available.

TypeScript DTOs and domain models for the Anarchitecture authentication stack. The package bundles:

Use it to validate inbound/outbound payloads, share typings between Angular/Nest bricks, and keep auth-specific logic consistent across tiers.

The unreleased 0.12 line uses explicit .js relative specifiers in emitted declarations for strict NodeNext consumers. DTOs, models, public entry points and CJS/ESM runtime formats are preserved. This transitive declaration fix is validated by the Auth Nest 11/12 packed-consumer matrix and can be backported independently to the 0.11.x maintenance line.

Migration guidance for the Better Auth realignment lives in the auth migration guide. Migration guidance for the contract-driven auth profile model lives in the auth contract migration guide.

Developer + AI Agent Start Here

Features

Authorization Contract

@anarchitects/auth-ts owns transport-neutral policy semantics and evaluation conformance, but does not enforce frontend or backend authorization by itself. Contracts owns the HTTP representation; mappings must preserve these semantics without loss.

PolicyRule

Serialized RBAC rules use the following contract:

This is the contract emitted by /auth/me, persisted through auth permission mapping, and consumed by Angular/Nest authorization helpers.

RoutePolicy

RoutePolicy is intentionally narrower than PolicyRule:

Use RoutePolicy when a consumer only needs to answer "may this user attempt this kind of work at all?" Concrete ownership or field-sensitive checks still belong to loaded resources and CASL ability evaluation in Angular/Nest layers.

This is the shared contract behind @anarchitects/auth-declarations route metadata and the coarse route-attempt helpers in @anarchitects/auth-angular. It is intentionally not the full resource-authorization contract.

Installation

npm install @anarchitects/auth-ts
# or
yarn add @anarchitects/auth-ts
# or
pnpm add @anarchitects/auth-ts

Entry points

Import path Description
@anarchitects/auth-ts Barrel re-export for core models plus the core/session DTO surface
@anarchitects/auth-ts/contracts Contract profile config, schema factories, compatibility helpers, and payload shaping
@anarchitects/auth-ts/dtos Core/session request-response schemas and DTO types (TypeBox)
@anarchitects/auth-ts/dtos/jwt JWT plugin-specific DTO types and schemas
@anarchitects/auth-ts/dtos/passkeys Passkey registration/authentication DTOs and route schemas
@anarchitects/auth-ts/models Domain models used for user/session/RBAC composition

Passkey ceremony contracts

Import the optional passkey contracts from @anarchitects/auth-ts/dtos/passkeys. They are not re-exported by the root or core DTO entry point. This package supplies shared schemas and inferred TypeScript types. Nest server verification consumes these contracts through AuthPasskeyService; package-owned HTTP endpoints and Angular browser orchestration remain work under epic #105.

Operation Request Successful response
Registration begin { authenticatorAttachment?: 'platform' | 'cross-platform' } WebAuthn creation options in JSON form
Registration finish { response: PasskeyRegistrationCredentialDTO, name?: string } Existing { success: boolean } envelope
Authentication begin {} for discoverable credentials WebAuthn request options in JSON form
Authentication finish { response: PasskeyAuthenticationCredentialDTO } Existing { user, rbac } session envelope

Each operation exports a request schema, response schema, their DTO types, and a route schema. For example:

import { PasskeyRegistrationFinishRequestSchema, PasskeyRegistrationFinishRouteSchema, type PasskeyRegistrationFinishRequestDTO } from '@anarchitects/auth-ts/dtos/passkeys';
import { Value } from '@sinclair/typebox/value';

function validateRegistration(payload: unknown): payload is PasskeyRegistrationFinishRequestDTO {
  return Value.Check(PasskeyRegistrationFinishRequestSchema, payload);
}

// Nest presentation can pass this directly to @RouteSchema once routes exist.
PasskeyRegistrationFinishRouteSchema;

The route schemas contain only body and response fields. HTTP paths and methods belong to Nest presentation; OpenAPI operation IDs and tags belong to the central spec tooling. Angular and Nest should import these types and schemas rather than copying them or exposing an authentication engine's internal types.

Registration requires an authenticated user. The server derives user identity, relying-party policy, and the expected challenge. Begin/finish correlation uses cookies, so adapters must preserve them across both requests. Authentication finish establishes the normal session and returns the shared user/RBAC envelope. Client-controlled user IDs, expected challenges, and verification policy are not accepted in request envelopes. A registration label is optional; supplied labels must contain a non-whitespace character and be at most 255 characters.

Binary fields use non-empty, unpadded base64url strings. Browser adapters must convert JSON options to browser inputs and serialize credentials before sending them. The shapes follow the WebAuthn JSON representations and accommodate SimpleWebAuthn browser serializers. Registration convenience fields are optional for older serializers; an assertion's userHandle may be absent or null. Adapters should normalize null when their verifier expects an omitted value. Transport hints accept future string values, and extension objects remain opaque to allow extension-specific data.

Schema validation checks transport structure. The server must still verify the challenge, origin, RP ID, credential ownership, signature, user verification, and counter policy, including consistency between id and rawId. These schemas do not perform cryptographic verification or enforce decoded binary lengths.

Existing passkey DTO exports follow this package's versioning and CI release workflow. Canonical HTTP contract versions are independent and require coordinated adoption under ADR-0016. There is no separate runtime contract-version constant or ceremony-body version. Tightening constraints or changing required fields is a breaking contract change.

Contract Profiles

@anarchitects/auth-ts owns the existing local auth-profile configuration/factory seam used by Nest and Angular. It remains part of the transitional baseline; profile customization must be audited against the applicable canonical HTTP contract before claiming conformance.

Use the factory whenever you need a custom auth profile or want one object that drives both runtime validation and UI behavior:

import { DefaultAuthContractConfig, assertContractCompatibility, createAuthContracts } from '@anarchitects/auth-ts';

assertContractCompatibility(DefaultAuthContractConfig, '1.0.0');

const contracts = createAuthContracts(DefaultAuthContractConfig);

contracts.registerRequestSchema;
contracts.registerFormMeta.name.required;
contracts.changePasswordFormMeta.newPassword.minLength;

Custom profiles are built by copying the default profile and overriding only the fields you want to change:

import { type AuthContractConfig, DefaultAuthContractConfig, createAuthContracts } from '@anarchitects/auth-ts';

const productProfile: AuthContractConfig = {
  ...DefaultAuthContractConfig,
  version: '1.0.0',
  register: {
    ...DefaultAuthContractConfig.register,
    name: {
      ...DefaultAuthContractConfig.register.name,
      required: true,
      minLength: 3,
      emptyStringPolicy: 'strip',
    },
  },
  login: {
    ...DefaultAuthContractConfig.login,
    password: {
      ...DefaultAuthContractConfig.login.password,
      minLength: 10,
    },
  },
};

const contracts = createAuthContracts(productProfile);

The static DTO schema exports such as RegisterRequestSchema and LoginRequestSchema remain available as default-profile convenience helpers. When a consumer needs profile customization, switch from those fixed exports to createAuthContracts(...).

Usage

Validating DTO payloads

import { Value } from '@sinclair/typebox/value';
import { LoginRequestSchema, LoginRequestDTO } from '@anarchitects/auth-ts/dtos';

const payload: LoginRequestDTO = {
  credential: 'user@example.com',
  password: 'secret123',
};

const errors = [...Value.Errors(LoginRequestSchema, payload)];
if (errors.length > 0) {
  // handle validation error details
}

Note: TypeBox does not ship built-in email validation. Register the format once in your runtime (for example, during app bootstrap):

import { FormatRegistry } from '@sinclair/typebox';

FormatRegistry.Set('email', (value: unknown): value is string => {
  return typeof value === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
});

Working with domain models

import { AuthUser, Role, Permission } from '@anarchitects/auth-ts';

function can(user: AuthUser, action: string, subject: string): boolean {
  const roles: Role[] = user.roles ?? [];
  return roles.some((role) => (role.permissions ?? []).some((permission: Permission) => permission.action === action && permission.subject === subject));
}

The models include timestamps (createdAt, updatedAt) and bidirectional relationships to support dynamic RBAC composition in persistence layers.

AuthUser is the preferred shared auth-domain user contract. User remains exported as a temporary compatibility alias for existing consumers.

AuthUser migration

Contract profile versioning

Scripts

Development notes

Snapshot test workflow

Contract profile versioning

Contributing

Auth DTOs are maintained in this package and consumed by Nest presentation routes. Update these schemas first, then regenerate OpenAPI via nx run api-specs:generate so every stack stays in sync.

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this package except in compliance with the License. You may obtain a copy of the License at the linked address or in the repository's LICENSE file. Unless required by applicable law or agreed to in writing, distributed code is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Canonical version and verification

This source line consumes @anarchitects/auth-contracts@0.1.0 through the domain TS compatibility bindings. See the canonical conformance guide for exact checks, configured-host obligations and remaining capability gates. Generated implementation OpenAPI and passing fixtures do not approve a deployed host's security profile. Existing runtime support and TypeBox exports remain.

Source Links