# Runtime Debugging and Failure Tracing

## Goals

- Trace failures across **HTTP → NATS → Verae → Zapier webhook** without redeploying.
- Keep secrets out of logs even when debug is enabled.
- Allow selective namespaces so production noise stays low.

## Enabling debug (runtime)

Debug is **off** when `DEBUG_VERAE` is unset or empty.

```bash
# Everything
export DEBUG_VERAE=1
# or
export DEBUG_VERAE=*

# Selected namespaces (comma-separated)
export DEBUG_VERAE=auth,nats,jobs,webhooks,http,billing,trace

# Minimum level: debug | info | warn | error
export DEBUG_VERAE_LEVEL=debug

# Optional: write to file as well as stderr
export DEBUG_VERAE_FILE=/var/log/verae-zapier-debug.log
```

Restart is **not** required if the process reads env only at boot — current implementation reads env at process start. To change flags:

```bash
# systemd / docker: update env and restart one replica
# or send future SIGHUP support (Phase 15)
```

### Docker example

```yaml
environment:
  DEBUG_VERAE: "auth,jobs,nats,webhooks"
  DEBUG_VERAE_LEVEL: "debug"
```

## Namespaces

| Namespace | What it traces |
|-----------|----------------|
| `auth` | API key resolve, session parse, login outcomes (no passwords) |
| `billing` | Entitlement checks, quota decisions, plan limits |
| `http` | Outbound Verae requests: method, path, status, duration |
| `nats` | Connect, publish, consume, ack/nak, stream ensure |
| `jobs` | Watch enqueue, poll attempts, terminal transitions |
| `webhooks` | Subscribe, deliver attempts, HTTP status to Zapier |
| `trace` | Correlation id enter/exit spans |
| `app` | Boot, config summary (redacted), shutdown |

`DEBUG_VERAE=1` or `*` enables **all** namespaces.

## Correlation IDs

Every inbound HTTP request should get a `traceId` (generated or from `X-Trace-Id` header).

That id is:

- returned optionally as `X-Trace-Id` on responses,
- attached to NATS payloads as `traceId`,
- included in every debug line for that flow.

Example log line:

```text
2026-08-11T16:00:00.000Z DEBUG jobs [trace=a1b2c3d4] poll attempt=3 jobId=550e… status=pending
```

## Redaction rules

Always redacted (replaced with `[REDACTED]`):

- Headers: `authorization`, `x-api-key`, `cookie`
- Fields named: `password`, `veraePassword`, `token`, `veraeToken`, `accessToken`, `apiKey`, `api_key`, `secret`
- String values matching: `Bearer …`, `zmw_…`, `zmt_…`, long JWTs (`eyJ…`)

`targetUrl` host is kept; query string may be stripped if it contains tokens.

## Using debug for common failures

### 401 from middleware

```bash
DEBUG_VERAE=auth,trace npm start
# reproduce Zapier connection test
# look for resolveAuthContext failures
```

### Job never completes / trigger never fires

```bash
DEBUG_VERAE=jobs,nats,webhooks,http
# confirm: watch published → poll status → event emitted → deliver POST status
```

### 402 quota

```bash
DEBUG_VERAE=billing
# confirm plan limits vs usage counters
```

### Verae upstream errors

```bash
DEBUG_VERAE=http,jobs
# status codes and paths only; body may be summarized
```

## Programmatic API

See [modules/debug.md](modules/debug.md) and source under `verae-zapier-middleware/src/debug/`.

```js
import { createDebugger } from '../debug/logger.js';
import { withTrace, getTraceId } from '../debug/trace.js';

const log = createDebugger('jobs');

log.debug('poll start', { jobId });
log.error('poll failed', { jobId, err: err.message });
```

## Tests

Phase 1 gate verifies:

- silence when disabled,
- namespace filtering,
- redaction,
- trace id propagation.

```bash
npm run gate:1
```

## Production caution

- Prefer staging with narrowed namespaces.
- Never commit files containing live debug output with customer data.
- CI should run with debug off except dedicated debug unit tests that assert redaction.
