Repository navigation
Release 1.44.1: DEV to main promotion - #3110
Merged
Merged
Conversation
…eedbackIrrelevant (#3080) The markFeedbackIrrelevant / unmarkFeedbackIrrelevant actions are bound to TutorialFeedback, but the admin UI renders their buttons inside the feedbackItems LineItem on a Tutorials object page. That invokes them through the navigation path Tutorials(...)/feedbackItems(<id>)/markFeedbackIrrelevant, so req.params is [tutorialKey, feedbackKey]. The handler read req.params[0] (the tutorial key), so the feedback lookup never matched -> consistent 'Feedback entry not found' 404. Resolve the bound entity's own key from the LAST req.params entry, which works for both the direct single-key path and the two-key navigation path. Add regression tests covering the navigation-path invocation for both actions.
…k-irrelevant fix(admin): Mark Irrelevant feedback action fails with 404 (#3080)
Hugo's `replace` is `replace INPUT OLD NEW`, so the pipe chain `$b64 | replace "+" "-" | replace "/" "_" | replace "=" ""` appended $b64 as the third (NEW) argument at each step, searching the literal "+"/"/"/"=" and discarding the base64 entirely. The emitted attachment-source param collapsed to "u=/=/", which the server base64url-decoded to an invalid URL — ingest failed and every tutorial download link returned 404 "Attachment unavailable" (old and new tutorials alike). Use nested replace() calls with the string as the first positional arg. Add a behavioral regression test that renders the real hook through Hugo and asserts the u= param base64url-decodes back to the exact source URL; the previous string-grep test never rendered Hugo, which is why the bug shipped.
…-3098 fix(attachments): correct base64url encode in render-link hook (#3098)
…3103) Content page loads (/concepts/:slug, /tutorials/:slug) intermittently returned a raw 500 "Internal Server Error". Root cause: serveStoredSlug reads BLOB metadata and the BLOB in two separate queries (to avoid the HANA LOB-locator-expiry gotcha). When metadata hits but the separate BLOB read returns nothing — the inconsistent-read window during a concurrent publish/delta-write to the mutable ContentCurrent, or a transient HANA locator blip — blobRow.CONTENT / toBuffer(null) threw, and serveHandler's catch surfaced raw JSON instead of the styled page. - serveStoredSlug: guard null/missing/non-Buffer/zero-length BLOB → return 'not-found' (styled 404); emit content.blob.missing metric. Both HANA and SQLite branches now coerce via toBuffer + share the guard. - serveHandler catch: serveNotFound(res, slug, 500) (styled page, 500 kept for monitoring) instead of raw JSON — mirrors the catalog branch and the fail-open pages path. - serveNotFound: no-store on 5xx so a transient blip served as a styled 500 is never edge-cached for 60s (404s stay cacheable). - resolveContentBlob: same toBuffer(null) guard in both branches, so the error-page/nav resolver can't throw on the identical race. Covers srv and srv-qa (both shim over @tutorials/content). Test: publish a slug, null its content column (metadata intact), assert styled 404 not 500. Red before, green after.
…e-500-resilience fix(content): degrade missing-BLOB race to styled page, not raw 500 (#3103)
…rror noise (#3102) KeyvCDS.set did a read-then-create/update (TOCTOU). Under multi-instance CF two instances both read 'no row', both INSERT the same CacheStore key, and the second INSERT violates the PK unique index — logged at error level (the PROD kg:rl:* rate-limiter noise) with the losing write dropped. Replace that branch with an atomic single-key UPSERT (last-write-wins) via a committed patch-package patch against cds-caching@2.1.0. Add a regression test driving the real KeyvCDS against an in-memory CAP fixture, modelling the TOCTOU window deterministically.
…3102) Add patch-package devDep + a postinstall hook so the cds-caching@2.1.0 UPSERT patch re-applies on every npm ci / npm install. prepare (git hooks) is left intact; both hooks fire on install.
…500 (#3103) Two compounding defects on /tutorials/:slug and /concepts/:slug serve paths: 1. serveStoredSlug read the BLOB metadata and the BLOB itself in separate queries (correct — avoids HANA LOB-locator-expiry). During a concurrent delta-write to mutable ContentCurrent (overwrite-in-place, no version pin) or a transient HANA locator blip the metadata row could survive while the BLOB SELECT returned null/undefined, causing toBuffer(null) or blobRow.CONTENT dereference to throw. 2. serveHandler's catch returned res.status(500).json({error:'Content retrieval failed'}) — raw JSON. All sibling branches (pageServeHandler, authorServeHandler, advocateServeHandler) already call serveNotFound; this path was the outlier. Fix: - Guard the BLOB read: null/undefined/non-Buffer/zero-length contentBuf → return 'not-found' (styled 404). Emits content.blob.missing metric for observability of the race condition. - Align serveHandler catch with siblings: serveNotFound(res, slug, 500) (styled page, status 500 preserved for monitoring). Test: publish a slug, null its content column (metadata intact), assert HTTP 404 not 500. Red before, green after.
…channels page roots
…ing-blob-500 # Conflicts: # packages/content/content-store.js
…-blob-500 fix(content-serve): degrade missing-BLOB race to styled 404, not raw 500 (#3103)
fix(#3095): concept/topic/channel page layout — container padding + cap relationship walls
…hing-upsert fix(cds-caching): atomic UPSERT in KeyvCDS.set to stop PK-collision error noise (#3102)
…es prod prune CF stages tutorials-srv with NODE_ENV=production, which prunes devDependencies. The postinstall hook runs `patch-package` (added in #3107 to apply patches/cds-caching+2.1.0.patch, a runtime dependency), but patch-package itself was only in devDependencies — so the prod prune removed the binary and staging failed with: npm error command sh -c patch-package npm error sh: 1: patch-package: not found (code 127) **ERROR** Unable to build dependencies: exit status 127 BuildpackCompileFailed Moving patch-package to dependencies keeps the binary in the pruned prod tree so the postinstall completes and the cds-caching patch applies at staging time. cds-caching is itself a runtime dependency, so the patch must apply in the production install. Broke the 2026-11-11 DEV deploy (tutorials-srv staging, all 3 retries).
fix(deploy): move patch-package to dependencies (unbreaks tutorials-srv staging)
Bump .deploy/mta.yaml 1.44.0 -> 1.44.1 (patch; the DEV->main delta is all fixes, no new features) and refresh hugo/data/whats_new.json with 14 merged PRs since 1.44.0 (total 1051 entries), summarized via the whats-new skill. This lands on DEV first; a separate DEV->main promotion PR ships it to PROD.
release 1.44.1 prep: version bump + whats-new refresh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 1.44.1 — DEV → main promotion
Promotes DEV to main for the 1.44.1 PROD release. DEV is ahead of main by 21 commits (8 fix PRs + release prep).
Merge commit (NOT squash) per
docs/developers/operations/branching-strategy.md§Release — keeps DEV an ancestor of main. A squash here would make DEV show as unmerged forever and replay the whole diff on the next release.What 1.44.1 ships to PROD (all fixes — patch bump 1.44.0 → 1.44.1)
patch-package→ dependencies (unbreaks CF staging)Post-merge — deploy is a SEPARATE, explicitly-authorized step
Merging this PR does not redeploy PROD. PROD deploy (full MTA from fresh
origin/main) runs separately after go-ahead.Content-rebuild dependencies to remember at PROD deploy time:
🤖 Generated with Claude Code