Pulp Engine Document Rendering
Get started
Release v0.80.0

Release v0.80.0 — Post-Hardening Audit Remediation

This release closes the highest-leverage findings from the post-hardening quality audit of v0.79.0. The theme: hardened-production mode is the marketed safe posture, but a cluster of insecure-by-default config footguns on the SSO and HA deployment shapes previously passed straight through it. v0.80.0 makes hardened mode the real safety bar for those shapes, fixes a credential-file permission hole, and cleans up several posture/documentation items.

All changes are backward-compatible except the SMTP TLS default (F7), which is a deliberate, opt-out-able security default change called out under Behavior changes below.

Behavior changes (read before upgrading)

  • Hardened mode + OIDC now requires OIDC_EDITOR_GROUPS to be set explicitly (F1). If you run with NODE_ENV=production/HARDEN_PRODUCTION=true and OIDC is enabled (OIDC_DISCOVERY_URL + OIDC_CLIENT_ID set), the server will refuse to boot until OIDC_EDITOR_GROUPS is set. Choose deliberately:
    • a comma-separated group list (recommended) — only those groups get editor;
    • an empty string — editor access only via OIDC_ADMIN_GROUPS;
    • * — acknowledge that every authenticated SSO user becomes an editor. The schema default is still *, so non-hardened and non-OIDC deployments are unaffected (non-hardened OIDC deployments now log a warning when * is in effect).
  • Scheduled email delivery enforces STARTTLS by default (F7). With SCHEDULE_SMTP_SECURE=false (the default, port 587), the SMTP transport now sets requireTLS: true. A relay that does not advertise STARTTLS will now fail closed instead of silently downgrading to plaintext. If you depend on a legacy plaintext-only relay, set SCHEDULE_SMTP_REQUIRE_TLS=false to restore the old behavior (not recommended).

Security

  • F1 — OIDC wildcard editor access no longer slips through hardening. New conditional hardening violation (sibling to the existing OIDC_REDIRECT_URI-https rule) + non-hardened startup warning. apps/api/src/config.ts.
  • F2 — editor user-registry file written 0o600. The file holds plaintext editor login keys. UserRegistry._persist() now removes any stale .tmp, writes owner-only, and re-chmods the final path after the atomic rename (POSIX; no-op on Windows). apps/api/src/lib/user-registry.ts.
  • F7 — STARTTLS enforced for scheduled email delivery (see Behavior changes). apps/api/src/lib/delivery/email.provider.ts, new SCHEDULE_SMTP_REQUIRE_TLS config.

High-availability

  • F3 — the bundled HA stack now ships Redis and shared rate limiting. docker-compose.ha.yml includes a redis service and sets RATE_LIMIT_STORE=redis on both replicas; the CI overlay docker-compose.ha.redis.ci.yml is reduced to CI determinism (tiny RATE_LIMIT_MAX, direct per-replica ports). A production startup warning is logged when RATE_LIMIT_STORE=memory is used with a database-backed (multi-instance-capable) storage mode.
  • F4 — HA user-registry divergence is surfaced and documented. A startup warning fires when OIDC auto-provisioning is combined with a file-backed registry in a multi-instance deployment. docs/ha-reference-architecture.md documents the single-writer / pre-seed constraint. A DB-backed user registry remains a deferred follow-up.

Documentation & metadata

  • F6 — triple-stash ({{{ }}}) raw-HTML caveat added to the TextNode JSDoc and the editor guide (it disables data escaping; never use it for lower-trust render data).
  • F8LICENSING.md clarified: licence enforcement is watermark-only; rendering never refuses. (The optional editor vendor-chunk split was deferred — it needs bundle-composition measurement first; the heavy libs are pulled in transitively, not via direct editor imports.)
  • F5@pulp-engine/sdk description corrected so it no longer implies a live PyPI listing.
  • Hardening docs across the deployment guide, OIDC guide, runbook, release checklist, README, and .env.example now describe the two conditional OIDC controls alongside the seven baseline controls.

Deferred (tracked follow-ups)

  • DB-backed editor user registry (the proper HA fix behind F4).
  • Actual npm/PyPI publication of the SDKs (pending trusted-publisher/registry setup).
  • Editor vendor-chunk split (pending bundle-composition measurement).

Tests

  • oidc-hardening.test.ts — new cases for the F1 gate (boot-fail when unset; boot-ok for */empty/ group-list; non-hardened wildcard warning).
  • user-registry-persist.test.ts — asserts 0o600 on the persisted file, including when a stale 0o666 .tmp pre-exists (POSIX-only assertions; round-trip checked cross-platform).
  • email-delivery-tls.test.ts — asserts requireTLS: true by default, the opt-out, and omission under implicit TLS.