Upgrade @arki/log 0.1.0 to 0.2.0

For @arki/[email protected] · source docs/upgrades/0.1.0-to-0.2.0.md

Apps that read isFailure results from untrusted JSON (API responses, queue messages, tool output) must check that nothing relied on a forged failure. Apps that only log can skip this and gain failure logging.

What changed

  • Security: outside data can no longer pass as a failure. isFailure (and @arki/log's failure check) now require the ~failure brand on the value's prototype and refuse it as an own property. Before, JSON such as {"~failure": true, "code": "x", "status": 500} from an API response, queue message or tool result counted as a failure, so boundaries skipped output schemas and answered with an attacker-chosen status or code. Real failures, revived ones and failures from a second copy of the package are still recognised.
  • A failure value from @arki/failure can be logged as a field: log.warn('lookup failed', { failure }). Every formatter and the OpenTelemetry sink print its code, message, status, data and remediation, plus causes: the cause chain, nearest first, through nested failures and thrown errors. The list stops at a cycle ([Circular]) or after 64 links ([MaxDepth]), the same limit as findCause. redact() paths reach into a failure's data and causes. @arki/log still has no dependencies: it knows a failure by its '~failure' brand. New exports: serializeFailure and the FailureLike type, which is now part of Value.

Public API changes

  • isFailure and the log failure check require the ~failure brand on the prototype. An own ~failure property no longer counts.
  • New exports: serializeFailure and the FailureLike type, now part of Value.

Steps

  1. Search for code that builds a failure-shaped object by hand, such as { '~failure': true, code, status }. It stops counting as a failure.

    // before: plain JSON passed as a failure
    const forged = { '~failure': true, code: 'x', status: 500 };
    // after: only values made by @arki/failure (or revived by it) count

    Create failures with @arki/failure. Revive stored ones with its revive function.

  2. Optional: log failures as fields. Formatters print code, message, status, data, remediation and causes.

    // before
    log.warn('lookup failed', { code: failure.code, message: failure.message });
    // after
    log.warn('lookup failed', { failure });

Verify

Run bun run test in the app. Then log one failure and check the output shows its code and causes.

All docs for @arki/[email protected]