CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ses

Hardened JavaScript for fearless cooperation through secure execution contexts and object-capability security

Pending
Overview
Eval results
Files

assertions.mddocs/

Assertion System

Enhanced assertion library with detailed error reporting, causal console integration, and rich diagnostic capabilities. The SES assertion system provides more informative error messages while protecting sensitive information from leaking through the exception path.

Capabilities

Core Assertion Function

The main assertion function with rich error reporting and type assertion capabilities.

/**
 * Assert that a condition is truthy with detailed error reporting
 * @param flag - The condition to test
 * @param details - Descriptive details about the assertion
 * @param errConstructor - Optional error constructor to use
 * @param options - Additional error creation options
 */
function assert(
  flag: any, 
  details?: Details, 
  errConstructor?: GenericErrorConstructor, 
  options?: AssertMakeErrorOptions
): asserts flag;

Usage Examples:

import 'ses';

lockdown();

// Basic assertion
assert(x > 0, 'x must be positive');

// Assertion with template literal details
const user = { name: 'Alice', age: 25 };
assert(user.age >= 18, assert.details`User ${user.name} must be adult, got age ${user.age}`);

// Assertion with custom error type
assert(user.name, 'User must have name', TypeError);

Type Assertions

Specialized assertion methods for common type checking scenarios.

/**
 * Assert expected typeof result with overloaded signatures for different types
 */
interface AssertTypeof {
  (specimen: any, typeName: 'bigint', details?: Details): asserts specimen is bigint;
  (specimen: any, typeName: 'boolean', details?: Details): asserts specimen is boolean;
  (specimen: any, typeName: 'function', details?: Details): asserts specimen is Function;
  (specimen: any, typeName: 'number', details?: Details): asserts specimen is number;
  (specimen: any, typeName: 'object', details?: Details): asserts specimen is Record<any, any> | null;
  (specimen: any, typeName: 'string', details?: Details): asserts specimen is string;
  (specimen: any, typeName: 'symbol', details?: Details): asserts specimen is symbol;
  (specimen: any, typeName: 'undefined', details?: Details): asserts specimen is undefined;
}

/**
 * Assert that a value is a string (shorthand for typeof)
 * @param specimen - Value to check
 * @param details - Optional error details
 */
function string(specimen: any, details?: Details): asserts specimen is string;

/**
 * Assert that two values are Object.is equal
 * @param actual - The actual value
 * @param expected - The expected value  
 * @param details - Optional error details
 * @param errConstructor - Optional error constructor
 * @param options - Optional error creation options
 */
function equal<T>(
  actual: unknown,
  expected: T,
  details?: Details,
  errConstructor?: GenericErrorConstructor,
  options?: AssertMakeErrorOptions
): asserts actual is T;

/**
 * Unconditionally fail an assertion
 * @param details - Error details
 * @param errConstructor - Optional error constructor
 * @param options - Optional error creation options
 */
function fail(
  details?: Details,
  errConstructor?: GenericErrorConstructor,
  options?: AssertMakeErrorOptions
): never;

Usage Examples:

import 'ses';

lockdown();

// Type checking
const value = getUserInput();
assert.typeof(value, 'string');
// Now TypeScript knows value is a string

// String assertion shorthand
assert.string(value, 'Input must be string');

// Equality assertion
const result = calculate();
assert.equal(result, 42, 'Calculation should return 42');

// Conditional failure
if (dangerousCondition) {
  assert.fail('System is in dangerous state');
}

Error Utilities

Utilities for creating, annotating, and formatting errors with enhanced diagnostic information.

/**
 * Create error objects with detailed logging
 * @param details - Error details  
 * @param errConstructor - Optional error constructor
 * @param options - Optional error creation options
 * @returns Created error object
 */
function error(
  details?: Details,
  errConstructor?: GenericErrorConstructor,
  options?: AssertMakeErrorOptions
): Error;

/**
 * Annotate errors with additional diagnostic details
 * @param error - Error object to annotate
 * @param details - Additional details to attach
 */
function note(error: Error, details: Details): void;

Usage Examples:

import 'ses';

lockdown();

// Create detailed errors
const createValidationError = (field, value) => {
  return assert.error(
    assert.details`Invalid ${field}: expected string, got ${value}`,
    TypeError,
    { errorName: 'ValidationError' }
  );
};

// Annotate existing errors
try {
  riskyOperation();
} catch (originalError) {
  assert.note(originalError, assert.details`Failed during step ${currentStep}`);
  throw originalError;
}

Template Literal Utilities

Template literal functions for creating rich, secure error messages.

/**
 * Create details tokens for error messages with safe substitution
 * @param template - Template literal strings
 * @param args - Substitution arguments
 * @returns Details token for error reporting
 */
function details(template: TemplateStringsArray | string[], ...args: any): DetailsToken;

/**
 * Create and throw errors using template literal syntax
 * @param template - Template literal strings
 * @param args - Substitution arguments
 * @throws Error with formatted message
 */
function Fail(template: TemplateStringsArray | string[], ...args: any): never;

/**
 * Quote values for safe inclusion in error messages
 * @param payload - Value to quote
 * @param spaces - JSON.stringify spacing option
 * @returns Stringable payload that renders quoted
 */
function quote(payload: any, spaces?: string | number): StringablePayload;

/**
 * Embed strings directly without quotes (use with caution)
 * @param payload - Value to embed
 * @param spaces - JSON.stringify spacing option  
 * @returns Stringable payload without quotes
 */
function bare(payload: any, spaces?: string | number): StringablePayload;

Usage Examples:

import 'ses';

lockdown();

// Template literal details
const { details: X, quote: q } = assert;

const validateUser = (user) => {
  user.age >= 18 || assert.fail(X`User ${user.name} must be adult, got age ${user.age}`);
  
  // Conditional failure with Fail
  user.email || Fail`User ${user.name} must have email address`;
  
  // Quote sensitive values
  const token = getSecretToken();
  assert(isValidToken(token), X`Invalid token format: ${q(token)}`);
};

// Create reusable details
const createUserError = (user, issue) => {
  return X`User validation failed for ${user.name}: ${issue}`;
};

Configuration and Error Handling

Error Creation Options

Options for controlling error creation behavior and metadata.

interface AssertMakeErrorOptions {
  /** Custom error name for console output identification */
  errorName?: string;
  
  /** Causal error that led to this error */
  cause?: Error;
  
  /** Array of errors for AggregateError-style reporting */
  errors?: Error[];
  
  /** Whether to sanitize error for security (default: true) */
  sanitize?: boolean;
}

Assert Factory Function

Factory function for creating custom assert functions with different error handling behavior.

/**
 * Create custom assert function with specific error handling
 * @param raise - Optional function called before throwing
 * @param unredacted - Whether to include unredacted details
 * @returns Configured assert function
 */
type MakeAssert = (raise?: Raise, unredacted?: boolean) => Assert;

/**
 * Function called when assertion fails, for custom termination behavior
 * @param reason - The error that caused the assertion failure
 */
type Raise = (reason: Error) => void;

Usage Examples:

import 'ses';

lockdown();

// Create custom assert with logging
const logAndAssert = assert.makeAssert((error) => {
  console.error('Assertion failed:', error.message);
  // Could terminate vat, process, etc.
});

// Use custom assert
logAndAssert(condition, 'This will be logged before throwing');

// Create unredacted assert for debugging
const debugAssert = assert.makeAssert(undefined, true);
debugAssert(false, debugAssert.details`Debug info: ${sensitiveData}`);

Advanced Usage Patterns

Secure Error Reporting

The SES assertion system provides two levels of detail for errors:

  1. Console Output: Full, unredacted details visible to console (assumed privileged)
  2. Exception Path: Redacted details that hide sensitive substitution values
import 'ses';

lockdown();

const sensitiveData = { token: 'secret-abc-123', userId: 'user-456' };

try {
  assert(false, assert.details`Authentication failed for user ${sensitiveData.userId} with token ${sensitiveData.token}`);
} catch (error) {
  // Exception message is redacted: "Authentication failed for user (a string) with token (a string)"
  console.log('Exception:', error.message);
  
  // Console sees full details when the error is logged
  console.error(error); // Shows actual values
}

Validation Pipelines

Using assertions for data validation with detailed error reporting:

import 'ses';

lockdown();

const validateUserData = (userData) => {
  const { details: X, quote: q } = assert;
  
  // Chain validations with descriptive errors
  assert.typeof(userData, 'object', X`User data must be object, got ${q(userData)}`);
  assert(userData !== null, 'User data cannot be null');
  
  assert.string(userData.name, X`User name must be string, got ${q(userData.name)}`);
  assert(userData.name.length > 0, X`User name cannot be empty`);
  
  assert.typeof(userData.age, 'number', X`User age must be number, got ${q(userData.age)}`);
  assert(userData.age >= 0, X`User age must be non-negative, got ${userData.age}`);
  assert(userData.age < 150, X`User age must be realistic, got ${userData.age}`);
  
  if (userData.email !== undefined) {
    assert.string(userData.email, X`User email must be string, got ${q(userData.email)}`);
    assert(/\S+@\S+\.\S+/.test(userData.email), X`User email must be valid format, got ${q(userData.email)}`);
  }
  
  return userData; // TypeScript now knows userData is properly shaped
};

// Usage
try {
  const validUser = validateUserData({
    name: 'Alice',
    age: 30,
    email: 'alice@example.com'
  });
  console.log('Valid user:', validUser);
} catch (error) {
  console.error('Validation failed:', error.message);
}

Contract-Based Programming

Using assertions for pre-conditions, post-conditions, and invariants:

import 'ses';

lockdown();

class BankAccount {
  #balance = 0;
  
  constructor(initialBalance) {
    assert.typeof(initialBalance, 'number', 'Initial balance must be number');
    assert(initialBalance >= 0, assert.details`Initial balance must be non-negative, got ${initialBalance}`);
    this.#balance = initialBalance;
  }
  
  deposit(amount) {
    // Pre-condition
    assert.typeof(amount, 'number', 'Deposit amount must be number');
    assert(amount > 0, assert.details`Deposit amount must be positive, got ${amount}`);
    
    const oldBalance = this.#balance;
    this.#balance += amount;
    
    // Post-condition  
    assert(this.#balance === oldBalance + amount, 'Balance should increase by deposit amount');
    assert(this.#balance >= 0, 'Balance should never be negative');
    
    return this.#balance;
  }
  
  withdraw(amount) {
    // Pre-conditions
    assert.typeof(amount, 'number', 'Withdrawal amount must be number');
    assert(amount > 0, assert.details`Withdrawal amount must be positive, got ${amount}`);
    assert(amount <= this.#balance, assert.details`Insufficient funds: requested ${amount}, available ${this.#balance}`);
    
    const oldBalance = this.#balance;
    this.#balance -= amount;
    
    // Post-conditions
    assert(this.#balance === oldBalance - amount, 'Balance should decrease by withdrawal amount');
    assert(this.#balance >= 0, 'Balance should never be negative');
    
    return this.#balance;
  }
  
  getBalance() {
    // Invariant check
    assert(this.#balance >= 0, 'Balance invariant violated');
    return this.#balance;
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-ses

docs

assertions.md

compartments.md

environment-hardening.md

index.md

modules.md

tools.md

tile.json