Release v0.82.0 — Post-audit follow-ups (security, API contract, editor safety)
This release closes the highest-leverage cluster from the post-hardening quality audit: an
OIDC token-replay path that contradicted the security docs, a tenant-isolation guarantee the
code did not enforce, a spreadsheet formula-injection gap in CSV/XLSX exports, an inconsistent
validation error contract, a deployment footgun around NODE_ENV, and an unconfirmed
destructive editor action. It also restores trustworthy review-time and local-dev signals.
Security
-
OIDC
id_tokenis no longer accepted as a rawAuthorization: BearerAPI credential (SEC-A1). The per-request OIDC provider was removed from the auth chain. Previously a rawid_tokenpresented as a Bearer token authenticated every protected route, bypassing the 5-minute freshness andOriginchecks thatPOST /auth/oidc/exchangeenforces and that the OIDC guide documents. Breaking change: SSO integrations must exchange theid_tokenat/auth/oidc/exchange(browser/embed → short-lived editor token); machine-to-machine callers use scoped API keys (API_KEY_*). The login/callback/complete/exchange/logout flows are unchanged. -
CSV / XLSX exports neutralize spreadsheet formula injection (SEC-R1). Data-derived cell values that begin with
= + - @(or tab/CR/LF) are prefixed with a literal-text apostrophe so they are not evaluated as formulas when the export is opened in Excel/LibreOffice/Sheets. Applies to table and pivot-table CSV/XLSX, including pivot row-dimension values, column keys, and subtotal labels. Numeric values (e.g. negative numbers, currency formatted from a number) are never altered, and author-defined column/measure labels are unaffected. -
ALLOW_NO_AUTHbackstop closes theNODE_ENVfootgun (SEC-A3). Credential and hardening enforcement previously keyed entirely offNODE_ENV(defaultdevelopment), so a barenode distthat forgotNODE_ENV=productionwould run with authentication silently disabled. Now, when authentication resolves to fully disabled (noAPI_KEY_*and no named-user registry), the server refuses to boot unlessALLOW_NO_AUTH=trueis set explicitly — independent ofNODE_ENV. The boot error leads with the real remedies (configure a credential or a named-user registry);ALLOW_NO_AUTH=trueis documented as a development/testing-only opt-out and emits an unmissable startup banner. TheNODE_ENV=testpath is exempt so the test suite is unaffected.
API
- Unified validation error contract (API-1/API-2).
RenderValidationError(render data fails the templateinputSchema) is now serialized identically on every route — the canonical{ error: "Validation Failed", code: "validation_failed", issues: [...], requestId }envelope from the global error handler. Previously the production DOCX/PPTX routes emitted a divergent{ error: "ValidationError", message }shape and every/render/preview/*route emitted aRenderErrorenvelope for the same failure. All preview422responses now declare the sameRenderError | ValidationErrorunion as production, so generated SDKs and/docs/jsonsee one consistent contract.
Editor
- “Restore to this version” now asks for confirmation (UX-2). Restoring is an irreversible live-template mutation (the render API and any labels pointing at the live version immediately serve the restored content). Both entry points — the version-list row and the compare-view footer — now open a confirmation dialog naming the target version before the restore runs.
Operability & CI
test-file-modenow runs on pull requests (OPS-2/EV-1). The file-mode integration suite needs no service container, Playwright, or Docker, so it is now a required-on-PR smoke alongside the corecijob. The heavier matrix (Docker build+smoke, SQL Server, e2e, Windows) remains gated to push/release to conserve Actions minutes.- Explicit
pnpm typecheckstep on the core CI job (EV-5). The PR gate now runs a repo-wide typecheck, matching the workflow’s self-description. - Release workflows retroactively strip stale
-latestaliases (REL-1). When a release becomeslatest,release.ymlandrelease-mirror.ymlnow sweep every superseded release and delete itsPulpEngine-Setup-latest.exe/pulp-engine-eval-latest.tar.gzaliases, so exactly one release ever serves the-latestdownload URLs the website links to. Previously the per-tag cleanup only fired on a rerun of the same tag, so old releases kept serving outdated “latest” builds — an evaluator pulling…/releases/download/<old-tag>/pulp-engine-eval-latest.tar.gzwould get a stale bundle. A one-time backfill removed the pre-existing aliases from all prior releases on both the private repo and the public mirror.
Documentation
- Tenant-isolation guarantees corrected (SEC-A2). The doc previously claimed filesystem asset
binaries were “rejected at startup” under multi-tenant mode. In fact they are tenant-path-prefixed
(
{tenantId}/…) and work; the doc now says so, recommendsASSET_BINARY_STORE=s3for multi-instance/HA and storage-enforced isolation, and a non-fatal startup advisory is logged for the filesystem + multi-tenant combination. (TheSTORAGE_MODE=filebackend is still rejected underMULTI_TENANT_ENABLED=true.) - OIDC and API guides updated for the v0.81.0 DB-backed editor registry (DOC-1/DOC-2). The OIDC
guide and the API guide’s named-user section now describe DB-backed persistence
(
EDITOR_USERS_DB, theeditor_userstable) for postgres/sqlserver mode instead of only the file path, and the OIDC guide documents that rawid_tokenBearer is not accepted (see SEC-A1). ALLOW_NO_AUTHadded to the deployment-guide environment reference; the editor guide notes the restore confirmation step.
Upgrade notes
- If any integration authenticated to the API by sending an OIDC
id_tokenasAuthorization: Bearer, switch it toPOST /auth/oidc/exchange(then use the returned editor token) or to a scoped API key. No first-party client used the direct path. - If you run the published artifact directly (not via the Docker image) without
NODE_ENV=productionand without any credentials, set a credential / named-user registry (recommended) orALLOW_NO_AUTH=truefor local development.