Skip to content

fix: test-infra and logger/config safety (#87, #88, #89, #90) - #94

Merged
NovaLux12 merged 2 commits into
mainfrom
fix/safety-logger-config
Oct 9, 2026
Merged

NovaLux12 merged 2 commits into
mainfrom
fix/safety-logger-config

Conversation

@NovaLux12

Copy link
Copy Markdown
Owner

Summary

Four small safety fixes to the test infrastructure and the logger/config layer, found by auditing the bridge against Medtronic's live API behaviour.

Also corrected four docs that overstated what the code does — the "secrets are never emitted" line in USER-GUIDE, "no PII" in the ARCHITECTURE module map, and the npx tsc --noEmit verification step in ARCHITECTURE and CONTRIBUTING.

Verification

npm test              → 288 passing / 24 files (baseline 246)
npm run typecheck     → clean (src, and src+test)

The new CI step is proven, not assumed: injecting const x: number = "nope" into a test file makes it fail with TS2322 while the old command still exits 0. Each redaction guard has a matching test, and reverting any one of them fails the suite. The redaction walk was audited against class instances, cross-realm objects, inherited and own toJSON, throwing getters and ownKeys traps, circular and shared references, __proto__ keys, typed arrays with attached fields, BigInt, 50 000-deep nesting and Proxy traps — nothing leaks and warn() never throws into its caller, which matters because it is called from error handlers.

Notes

Redaction is key-name matching, not content inspection, and the legacy log() helper takes positional arguments rather than a fields object so it does not redact at all. Both limits are now stated in USER-GUIDE instead of being implied away — a logger that claims more than it does is worse than one that doesn't.

Closes #87, #88, #89, #90.

- #87 CI now typechecks test/ too via tsconfig.test.json. Previously no
  type error in any test file was visible to tsc or CI — how a TS2322 in a
  test went unnoticed. The override restates include AND exclude (the base
  config excludes test/, which would otherwise silently override include),
  sets rootDir "." (base sets rootDir "src", which trips TS6059) and
  noEmit, so it cannot dump dist/src + dist/test over the build layout if
  someone drops the flag. Verified by injecting a type error into a test
  file and watching the new step fail. Adds `npm run typecheck`, which is
  what CI runs and what the contributor docs now point at.

- #88 logger.ts redaction widened to authorization/bearer/api-key/
  credentials/passwd/cookie spellings and made recursive: sensitive keys
  are redacted at any depth through objects and arrays. Cycles terminate
  as [CIRCULAR], a shared (non-cycle) reference renders once per
  occurrence, and the ways a value can evade the walk are closed:
    - an inherited toJSON is replaced — a #private-field class whose
      toJSON returns its secret has no own keys, so JSON.stringify would
      invoke it after redaction;
    - a throwing getter, a throwing ownKeys trap, and a throwing toJSON
      getter each yield [UNREADABLE] rather than propagating out of
      warn(), which matters because warn() is called from error handlers;
    - nesting past 100 levels yields [MAX_DEPTH] rather than a RangeError;
    - a bare typed array has no toJSON, so JSON.stringify would emit every
      own property: its indices pass through but a NON-index key attached
      to it is redacted like any other field;
    - a payload JSON.stringify rejects (BigInt) degrades to
      log_stringify_error while KEEPING ts/level/msg, because a bare error
      flag with no level and no message is untriageable;
    - a container-shaped value that reduces to a marker string is coerced
      back to an object, so it cannot be spread into a character map.
  Plus the module's first direct tests.

  Key-name matching remains best-effort, and the legacy log() helper takes
  positional args rather than a fields object so it does not redact at
  all. Both are now stated in USER-GUIDE instead of being implied away.

- #89 first direct coverage for src/config.ts: required-var errors,
  safety-relevant defaults, LOG_FORMAT fallback, CUSTOMCONNSTR_ fallback,
  and the CARELINK_QUIET truthiness table pinned as current behaviour.
  The env scrub is case-insensitive over every prefix readEnv honours
  (lowercase keys included), so an ambient MMCONNECT_COUNTRYCODE cannot
  break the safety-default assertions. USER-GUIDE and .env.example now
  state the coercion: only the literal "false" enables verbose mode.

- #90 documented that verbose mode logs the full upload payload, in the
  CARELINK_QUIET and LOG_FORMAT rows and on upload() itself.

- Docs corrected rather than left absolute: "secrets are never emitted"
  (USER-GUIDE), "no PII" (ARCHITECTURE module map), and the
  `npx tsc --noEmit` verification step in ARCHITECTURE + CONTRIBUTING.

Tests: 288 passing (baseline 246). `npm run typecheck` clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI never typechecks test/ — tsconfig excludes it, so a TS2322 error in a test file ships green

1 participant