)]}'
{
  "log": [
    {
      "commit": "532d86d3e2eb9dee37f791a1d49ab27e8582fcc8",
      "tree": "bdfa81a1c6f6dade33eb0e69bd1c3e9b5328d395",
      "parents": [
        "2593fc0839cb006242b1a734d62de48c386d46e7"
      ],
      "author": {
        "name": "Lee SuJung",
        "email": "153787023+xhaktm00@users.noreply.github.com",
        "time": "Fri Aug 21 00:58:48 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 21 00:58:48 2026 +0900"
      },
      "message": "[ZEPPELIN-6582] New UI: clearing a paragraph in collaborative mode throws and does not sync the empty text\n\n### What is this PR for?\r\n`ParagraphComponent.sendPatch()` guards `dirtyText` with a falsy check:\r\n\r\n```typescript\r\nsendPatch() {\r\n  if (!this.dirtyText) {\r\n    throw new Error(\u0027dirtyText is required\u0027);\r\n  }\r\n```\r\n\r\nAn empty string is a valid paragraph state, but `!\u0027\u0027` is `true`, so deleting the last character of a paragraph throws before `patchParagraph(...)` is reached. The empty edit never leaves the client, other sessions keep the previous non-empty text, and `originalText` stays at the stale value — so even later edits are diffed against text the paragraph no longer has.\r\n\r\nThe guard was introduced while migrating the frontend to `strict: true` in ZEPPELIN-6252, which intended to preserve existing behaviour; the previous runtime accepted empty paragraph text.\r\n\r\n`dirtyText` is typed `dirtyText?: string`, so the only value the guard needs to reject is `undefined`. This PR checks for that instead — the same check `saveParagraph()` already performs on the same field a few lines below:\r\n\r\n```typescript\r\nif (this.dirtyText \u003d\u003d\u003d undefined) {\r\n```\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Accept the empty string in `sendPatch()` while still rejecting an unset `dirtyText`\r\n* [x] Add frontend coverage for the non-empty-to-empty transition\r\n\r\n### What is the Jira issue?\r\n* [ZEPPELIN-6582](https://issues.apache.org/jira/browse/ZEPPELIN-6582)\r\n\r\n### How should this be tested?\r\nNew spec `paragraph.component.spec.ts` covers both directions of the guard: clearing a paragraph should send a patch turning `\u0027abc\u0027` into `\u0027\u0027` and advance `originalText` to `\u0027\u0027`, and an unset `dirtyText` should still throw without calling `patchParagraph`. It follows the existing `react-mount.directive.spec.ts` style, constructing the component without its constructor.\r\n\r\n```\r\ncd zeppelin-web-angular\r\nnpm run test:shell\r\nnpm run lint\r\n```\r\n\r\n**I could not run `test:shell` locally** — `vitest` and `jsdom` are missing from this checkout and the npm registry returned `503` throughout, so please treat CI as the authoritative check on the new spec. Verified instead: `tsc --noEmit` passes, the pre-commit hook ran eslint and prettier clean, and `patch_make(\u0027abc\u0027, \u0027\u0027)` does apply back to `\u0027\u0027`. Not verified: that `Object.create(...prototype)` construction works under the vitest runtime.\r\n\r\nManual: open the same note in two sessions, type into a paragraph, then delete all of it. Before this change the editing session logs `Error: dirtyText is required` and the other session keeps the old text; after it, both end up with an empty editor and no console error.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No — this only widens an input guard, and non-collaborative saving goes through `saveParagraph()`, which is unchanged\r\n* Does this needs documentation? No\r\n\r\n### Note for reviewers\r\nZEPPELIN-6563 also touches `sendPatch()` (it attaches checksums to each patch). The two changes are independent — this one is about the guard at the top of the method — but whichever merges second will need a trivial rebase.\n\nCloses #5428 from xhaktm00/ZEPPELIN-6582.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "2593fc0839cb006242b1a734d62de48c386d46e7",
      "tree": "1e18497a0b261773ac76f1e8e1565af5a5ce5b32",
      "parents": [
        "f2f34cd548ef03ca7b0c438e63709d0cc12a9de4"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Thu Aug 20 16:59:28 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 20 16:59:28 2026 +0900"
      },
      "message": "[HOTFIX] Validate note access for interpreter bindings\n\n### What is this PR for?\n\nEnsure that interpreter binding operations follow the permissions of the associated note.\n\n- Reading interpreter bindings requires reader permission.\n- Updating interpreter bindings requires writer permission.\n- Requests without the required permission stop before returning binding data or applying changes.\n- Add regression tests for permitted and rejected read/write requests.\n\n### What type of PR is it?\n\nHot Fix\n\n### Todos\n\n* [x] Add note permission checks for interpreter binding operations\n* [x] Add regression tests\n* [x] Run `NotebookServerTest`\n\n### What is the Jira issue?\n\nN/A\n\n### How should this be tested?\n\n```bash\nmkdir -p spark/interpreter/target\n./mvnw -pl spark/interpreter resources:resources\u003cat\u003ecopy-interpreter-setting\n./mvnw -pl zeppelin-server -Dtest\u003dNotebookServerTest test\n```\n\nResult: 25 tests run, 0 failures, 0 errors.\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n* Does the license files need to update? No.\n* Is there breaking changes for older versions? No API compatibility changes. Requests without the required note permission are now rejected as intended.\n* Does this needs documentation? No.\n\nCloses #5431 from jongyoul/codex/security-interpreter-bindings-authz.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "f2f34cd548ef03ca7b0c438e63709d0cc12a9de4",
      "tree": "6b6e009ce3d69a1ed3edd8ff1b343e84ee1dfd28",
      "parents": [
        "e3212c834ca8f02ceecf6044e2b77f628538c216"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Thu Aug 20 16:58:46 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 20 16:58:46 2026 +0900"
      },
      "message": "[HOTFIX] Avoid shell evaluation of interpreter launch arguments\n\n### What is this PR for?\n\nThis PR makes interpreter launch argument handling predictable across configuration and impersonation modes.\n\nThe dependency downloader command is now executed directly as an argument array instead of being evaluated as a shell command. Classpath wildcards, spaces, JVM options, and other configured values therefore remain literal process arguments.\n\nWhen user impersonation is enabled, `%conf` and session-scoped configuration reject new environment-variable-style overrides. Existing operator-provided interpreter settings remain unchanged, and rejected updates are not partially applied.\n\n### What type of PR is it?\n\nHot Fix\n\n### Todos\n\n* [x] Execute downloader arguments without shell evaluation\n* [x] Preserve classpath and JVM argument behavior\n* [x] Validate user-provided environment overrides in impersonation mode\n* [x] Add unit and shell-level regression tests\n\n### What is the Jira issue?\n\nN/A\n\n### How should this be tested?\n\n```bash\nZEPPELIN_LOCAL_IP\u003d127.0.0.1 ./mvnw -pl zeppelin-server \\\n  -Dtest\u003dConfInterpreterTest,SessionConfInterpreterTest,InterpreterShellScriptTest,StandardInterpreterLauncherTest test\n\n./mvnw -pl zeppelin-server -DskipTests -Prat apache-rat:check\n```\n\nThe tests cover literal argument handling for classpaths, wildcards, JVM options, rejected environment overrides with impersonation enabled, allowed updates without impersonation, and preservation of existing operator configuration.\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5429 from jongyoul/codex/security-interpreter-eval.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "e3212c834ca8f02ceecf6044e2b77f628538c216",
      "tree": "d5de1e3fbbd4e659ca977d4147b8bae6a59d67e4",
      "parents": [
        "2cc438b72501a202635f064f084d53cad9c04f5f"
      ],
      "author": {
        "name": "Coen90",
        "email": "81370558+Coen90@users.noreply.github.com",
        "time": "Wed Aug 19 17:32:31 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 19 17:32:31 2026 +0900"
      },
      "message": "[ZEPPELIN-6451] Add default NotebookRepo settings methods to remove duplicated placeholder implementations\n\n### What is this PR for?\r\nSeveral `NotebookRepo` implementations (S3, GCS, OSS, Azure, Mongo, FileSystem, InMemory) duplicated the same placeholder code for `getSettings` / `updateSettings` — returning an empty list or logging \"Method not implemented\".\r\n\r\nThis PR centralizes that placeholder behavior as `default` methods on the `NotebookRepo` interface:\r\n* `getSettings` returns an empty list and logs at DEBUG level (querying settings is a normal read path, so it should not produce warning noise).\r\n* `updateSettings` is a no-op and logs at WARN level (an ignored update attempt is worth surfacing).\r\n\r\nAll duplicated overrides are removed from the plugin repos, `InMemoryNotebookRepo`, and the test helper repos in `NotebookTest`. Repos with real settings logic (e.g. `VFSNotebookRepo`, `GitNotebookRepo`) keep their own overrides and are unaffected. Since these are `default` interface methods, existing third-party `NotebookRepo` implementations remain source- and binary-compatible.\r\n\r\n### What type of PR is it?\r\nRefactoring\r\n\r\n### Todos\r\n* [x] - Add default `getSettings` / `updateSettings` implementations to `NotebookRepo`\r\n* [x] - Remove duplicated placeholder overrides from S3 / GCS / OSS / Azure / Mongo / FileSystem / InMemory repos and test helpers\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6451\r\n\r\n### How should this be tested?\r\n* Pure refactoring with behavior preserved — the existing `zeppelin-server` test suite covers the affected code paths:\r\n  `./mvnw test -pl zeppelin-server -am`\r\n* CI should pass.\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No — `default` methods keep existing implementations compatible; the only visible change is the log level/message of the placeholder behavior.\r\n* Does this needs documentation? No\n\nCloses #5411 from Coen90/ZEPPELIN-6451-default-notebookrepo-settings.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "2cc438b72501a202635f064f084d53cad9c04f5f",
      "tree": "9e1b37ce8c326015fd4b62c9e280b4383ad58754",
      "parents": [
        "8adeb6a402e9aa7ad228afee5324fdc7eee1de96"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Tue Aug 18 23:01:29 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 18 23:01:29 2026 +0900"
      },
      "message": "[ZEPPELIN-5235] Add Cancel all paragraphs button to the new UI\n\n### What is this PR for?\r\nThe note action bar has a run-all button but no way to stop a note from the UI. Stopping a running\r\nnote is only reachable through `DELETE /api/notebook/job/{noteId}`, so a user who starts a long note has\r\nto leave the page and issue a REST call, or cancel each paragraph one by one.\r\n\r\nThis adds a `Cancel all paragraphs` button next to run-all in the new UI. The button sends a new\r\n`CANCEL_ALL_PARAGRAPHS` websocket message, and `cancelAllParagraphs()` in `NotebookService` aborts\r\nevery paragraph of the note that has not terminated yet.\r\n\r\nThe abort loop already existed inline in `stopNoteJobs()` in `NotebookRestApi`. It is extracted to\r\n`Note.abortAll()` so the REST endpoint and the websocket handler share one implementation instead of\r\ndrifting apart. Permission handling follows the existing run path: the service checks\r\n`Permission.RUNNER` the same way `cancelParagraph()` does, and the note is reached through\r\n`notebook.processNote()` so the note lock is held while paragraphs are aborted.\r\n\r\nNo new cancellation mechanism is introduced. `Note.abortAll()` calls the existing `Paragraph.abort()`,\r\nwhich delegates to `interpreter.cancel()` exactly as single-paragraph cancel does today. The button is\r\ndisabled in revision view and while no paragraph is running.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n* [x] - Extract `Note.abortAll()` and reuse it from `stopNoteJobs()`\r\n* [x] - Add `CANCEL_ALL_PARAGRAPHS` op and `NotebookService.cancelAllParagraphs()`\r\n* [x] - Add the button to the new UI action bar and the message to the SDK\r\n* [x] - Unit tests for the notebook, service and socket layers\r\n\r\n### What is the Jira issue?\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-5235\r\n\r\n### How should this be tested?\r\n`NotebookServiceTest` covers the success path, the forbidden path for a non-runner, and an unknown\r\nnote id. `NotebookServerTest` covers the op routing. `NotebookTest` covers `Note.abortAll()` leaving\r\nterminated paragraphs alone.\r\n\r\nManually: create a note with six python paragraphs where the first two finish within a few seconds and\r\nthe rest sleep for minutes, run all, then press the button while a paragraph is running. The running\r\nparagraph moves to ABORT, the finished ones keep FINISHED, and paragraphs that never started stay\r\nuntouched.\r\n\r\n### Screenshots (if appropriate)\r\nhttps://github.com/user-attachments/assets/ebd5e205-ad18-4340-9995-2fcfd10f5d9b\r\n\r\n### Questions:\r\n* Does the license files need to update? No.\r\n* Is there breaking changes for older versions? No. The REST behaviour is unchanged and the new op is additive.\r\n* Does this needs documentation? No.\r\n\n\nCloses #5425 from HwangRock/ZEPPELIN-5235-cancel-all.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "8adeb6a402e9aa7ad228afee5324fdc7eee1de96",
      "tree": "2261aeffbf7871a01a88a867cd00669fc1abcfbb",
      "parents": [
        "14cdf8437224adff08864de05b810f7149a82119"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Tue Aug 18 17:55:22 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 18 17:55:22 2026 +0900"
      },
      "message": "[HOTFIX] Validate interpreter library lookup\n\n### What is this PR for?\n\nThis PR makes interpreter library lookup more robust and predictable.\n\nThe previous lookup used the interpreter setting name directly as the on-disk directory, while dependency repositories are stored by setting ID. The updated lookup resolves the registered interpreter setting first, uses its ID for the repository, and returns only direct, regular JAR entries expected by the library synchronization flow. Missing and unsupported entries are ignored.\n\nThis also preserves compatibility when an interpreter setting name differs from its setting ID.\n\n### What type of PR is it?\n\nHot Fix\n\n### Todos\n\n* [x] Validate interpreter and library lookup inputs\n* [x] Resolve repositories through registered interpreter settings\n* [x] Preserve setting-name-to-setting-ID compatibility\n* [x] Add unit tests for accepted and ignored entries\n\n### What is the Jira issue?\n\nN/A\n\n### How should this be tested?\n\n```bash\n./mvnw -pl zeppelin-server \\\n  -Dtest\u003dRemoteInterpreterEventServerTest,RemoteInterpreterEventServerLibraryTest test\n\n./mvnw -pl zeppelin-server -DskipTests \\\n  org.apache.rat:apache-rat-plugin:check -Prat\n```\n\nThe unit tests cover registered JAR retrieval and metadata, setting-name-to-setting-ID resolution, unsupported lookup inputs, unregistered settings, non-JAR files, directories, and symbolic links.\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5423 from jongyoul/codex/security-getlibrary-path.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "14cdf8437224adff08864de05b810f7149a82119",
      "tree": "e23bcd5619c975797f901ce26d76390410d91370",
      "parents": [
        "cd700db60e01e9def588a64696ffde17125b6263"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Sun Aug 16 20:34:02 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 16 20:34:02 2026 +0900"
      },
      "message": "[ZEPPELIN-6640] Theme the React remote from the host instead of the shell\u0027s CSS\n\n### What is this PR for?\r\n\r\nThe React remote never learns which theme the shell is in. `PublishedParagraph` wraps its tree in antd\u0027s `ConfigProvider` but only sets `token.fontFamily`, so antd always builds its styles from the default (light) algorithm.\r\n\r\nDark mode still looks correct today, but not for a reason either side declares. `ThemeService` writes `data-theme` and a `dark` class onto the document root, and the shell\u0027s global ng-zorro-antd stylesheet targets the same `.ant-*` class names the remote\u0027s markup happens to use, so the shell\u0027s dark rules land on top of the remote\u0027s own light CSS-in-JS. In the published paragraph with `?react\u003dtrue` in dark mode, `.ant-table` computes to `rgb(31, 31, 31)`. Disable every stylesheet except the remote\u0027s own injected `style[data-css-hash]` tags and the same element becomes `rgb(255, 255, 255)` on the dark page.\r\n\r\nAnything the shell\u0027s CSS cannot reach stays light. The charts in `TableVisualization` are drawn on a canvas, and no chart config sets axis, grid or legend colors, so chart.js v4 defaults apply (`#666` text, `rgba(0, 0, 0, 0.1)` grid). Against the dark page background (`#141414`) the tick and category labels sit at about 3.2:1, below the 4.5:1 WCAG AA threshold for text, and the grid lines are effectively invisible.\r\n\r\nThis gives the remote the theme as an input instead of letting it inherit one by accident. `src/theme/hostTheme.ts` reads the theme the shell already publishes on the document root and follows it while mounted, `ZeppelinThemeProvider` selects antd\u0027s dark or default algorithm from it and exposes the resolved value through context for code that draws outside antd, and `chartTheme.ts` sets the two chart.js globals that ticks, legend labels and grid lines resolve from.\r\n\r\nThe theme is read from the DOM rather than passed in through `reactProps`. The published paragraph still mounts through its own `window.reactApp` path, so a props based version would have to be wired into that path as well as the directive, and the two host files it would touch are the ones ZEPPELIN-6564 and ZEPPELIN-6565 are currently changing. Reading the attribute the shell already publishes for its own CSS covers both mount paths and needs no host change, and a theme toggle then re-renders the remote without going through change detection. If you would rather keep host state flowing in through props, having the provider take an explicit `theme` prop is a small follow-up.\r\n\r\nMatching the shell pixel for pixel is not the goal. antd\u0027s dark container token is `#141414` where ng-zorro\u0027s is `#1f1f1f`, and where the shell\u0027s global rules still win, they win.\r\n\r\n### What type of PR is it?\r\n\r\nBug Fix\r\n\r\n### Todos\r\n\r\nNone\r\n\r\n### What is the Jira issue?\r\n\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6640\r\n\r\n### How should this be tested?\r\n\r\n* New vitest specs under `projects/zeppelin-react/src/theme/`: theme resolution from the document root and its fallbacks, live updates when the shell toggles the theme, antd algorithm selection asserted through `theme.useToken()`, and the chart.js defaults. The project\u0027s suite is green at 29 specs. Note that unit tests do not gate CI yet (ZEPPELIN-6566).\r\n* Manual check in both modes on the published paragraph with `?react\u003dtrue`, on a paragraph with a TABLE result. Switch to Bar Chart in dark mode: the axis labels, legend and grid lines are readable where they were not. The table view and light mode are unchanged.\r\n* To see the cause rather than the symptom, disable the host\u0027s stylesheets in devtools. On master the remote\u0027s table turns white on the dark page. Here it stays dark, and the rule the remote injects reads `color: rgba(255, 255, 255, 0.85)`.\r\n* A production build of the remote (`npm run build`).\r\n\r\n### Screenshots (if appropriate)\r\n\r\nbefore\r\n\u003cimg width\u003d\"900\" height\u003d\"620\" alt\u003d\"1-before-chart-dark\" src\u003d\"https://github.com/user-attachments/assets/4bbe9715-e30f-43fc-b19d-dea71e51d4c8\" /\u003e\r\n\r\nafter\r\n\u003cimg width\u003d\"900\" height\u003d\"620\" alt\u003d\"2-after-chart-dark\" src\u003d\"https://github.com/user-attachments/assets/21631d6e-d636-4768-91af-09d2e8347887\" /\u003e\r\n\r\n### Questions:\r\n\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? Yes, `projects/zeppelin-react/README.md` gains the provider step in \"Adding a new React module\"\r\n\r\n\n\nCloses #5420 from kimyenac/ZEPPELIN-6640.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "cd700db60e01e9def588a64696ffde17125b6263",
      "tree": "dd1eb776ce4e5803735f22a6b95b3189ae8ef3a3",
      "parents": [
        "d64897a0abdb4c9f720cf26faf95861c0e117ef1"
      ],
      "author": {
        "name": "ChanHo Lee",
        "email": "chanholee@apache.org",
        "time": "Sat Aug 15 19:34:09 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Aug 15 19:34:09 2026 +0900"
      },
      "message": "[ZEPPELIN-6641] Fix stale rationale in the reportError comment\n\n### What is this PR for?\nThe `reportError` comment in `ReactMountDirective` claimed that a `markForCheck()` issued from outside the Angular zone has nothing to flush it. Since Angular 18 that is not accurate: hybrid scheduling notifies `ChangeDetectionSchedulerImpl`, and a tick is scheduled for exactly that case (measured at 1 to 4 ms on a running dev server, see the ZEPPELIN-6565 comment).\n\nThis states a rationale that does not depend on internal scheduling behavior. Comment only, no behavior change.\n\n### What type of PR is it?\nImprovement\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6641\n\n### How should this be tested?\nComment-only change, nothing to test.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5424 from tbonelee/ZEPPELIN-6641.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "d64897a0abdb4c9f720cf26faf95861c0e117ef1",
      "tree": "9a2a387df3e764caf3ca3b823c48c26fdecd4f62",
      "parents": [
        "e5b698701a6fefe71cb5489015b104b1412c34ec"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Sat Aug 15 17:58:32 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Aug 15 17:58:32 2026 +0900"
      },
      "message": "[ZEPPELIN-6565] Re-enter Angular zone for React remote callbacks\n\n### What is this PR for?\r\nThis PR fixes `ReactMountDirective` so callbacks invoked by a mounted React remote re-enter the Angular zone before calling back into the Angular host.\r\n\r\n`ReactMountDirective` mounts and updates React remotes inside `ngZone.runOutsideAngular()`. The directive already used `ngZone.run()` for errors reported through its own `reportError()` path, but props were passed to the remote unchanged. As a result, a remote such as the React paragraph footer could call `props.onError()` directly from outside the Angular zone. \r\n\r\nFor an Angular `OnPush` host component, that can mark the component dirty without scheduling change detection, delaying the fallback UI until some later zone-scheduled work occurs.\r\n\r\nThis change wraps host callbacks as props enter `ReactMountDirective`, while keeping the original props (`latestRawProps`) available for directive-internal error reporting. The wrapped props (`latestProps`) are passed to both `mount()` and `update()`, so React remote callbacks consistently run through the Angular zone boundary.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6565\r\n\r\n### How should this be tested?\r\nRun the shell unit tests:\r\n```sh\r\ncd zeppelin-web-angular\r\nnpm run test:shell\r\n```\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5417 from miinhho/fix/react-lifecycle-outside.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "e5b698701a6fefe71cb5489015b104b1412c34ec",
      "tree": "7d3b0a7cdfa9a01540fed38b13e988f7beb7be18",
      "parents": [
        "9f7092b4a82e0fb42641cb9fc55eda463ee6dff3"
      ],
      "author": {
        "name": "github-actions[bot]",
        "email": "41898282+github-actions[bot]@users.noreply.github.com",
        "time": "Sat Aug 15 13:02:37 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Aug 15 13:02:37 2026 +0900"
      },
      "message": "[HOTFIX] Refresh zeppelin-react lockfile for npm audit\n\n### What is this PR for?\n\nRefresh the zeppelin-react lockfile with compatible updates suggested by `npm audit fix`.\nThe daily audit remediation workflow generated this change after the required high-severity audit began failing.\n\n### What type of PR is it?\n\nHot Fix\n\n### What is the Jira issue?\n\nN/A - automated dependency maintenance.\n\n### How should this be tested?\n\n- `npm ci --ignore-scripts --no-audit` in `zeppelin-web-angular`\n- `npm ci --ignore-scripts --no-audit` in `zeppelin-web-angular/projects/zeppelin-react`\n- `npm audit --audit-level\u003dhigh`\n- `npm run lint`\n- `npm test`\n- `npm run build`\n\nAll commands passed before this PR was created.\n\n\nCloses #5422 from github-actions[bot]/automation/npm-audit-fix-zeppelin-react.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "9f7092b4a82e0fb42641cb9fc55eda463ee6dff3",
      "tree": "ae52e7615ebe50d73935e313445c2373298fe721",
      "parents": [
        "0f4991d6681d8b9c407e97f355cbf41d290df6d3"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Fri Aug 14 14:55:29 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 14 14:55:29 2026 +0900"
      },
      "message": "[MINOR] Add daily npm audit remediation workflow\n\n### What is this PR for?\n\nAdd a daily and manually triggered workflow that detects high/critical `npm audit` failures in `zeppelin-react`.\n\nWhen a lockfile-only fix is available, the workflow:\n\n- changes only `zeppelin-react/package-lock.json`;\n- validates audit, lint, tests, and production build;\n- creates or updates one Draft PR from a fixed automation branch;\n- skips creating a duplicate when the lockfile content is unchanged.\n\nIt never uses `npm audit fix --force`, pushes directly to `master`, or merges automatically.\n\n### What type of PR is it?\n\nImprovement\n\n### What is the Jira issue?\n\nN/A\n\n### How should this be tested?\n\n- The workflow\u0027s `prepare` job passed on this PR.\n- The end-to-end remediation path passed audit, lint, 14 tests, and production build locally.\n\n\nCloses #5390 from jongyoul/codex/daily-npm-audit-fix-pr.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "0f4991d6681d8b9c407e97f355cbf41d290df6d3",
      "tree": "a2a70246cf594d24c07ef5e81c4cd6817976e29a",
      "parents": [
        "c199b4074278316c99e5cc53304aeca3992b5f73"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Thu Aug 13 09:11:06 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 09:11:06 2026 +0900"
      },
      "message": "[ZEPPELIN-6432] Modernize the Jekyll documentation build\n\n### What is this PR for?\nModernize the versioned documentation build and keep its publication output compatible with `zeppelin-site`.\n\n- Replace `github-pages` / Jekyll 3.9.5 / Redcarpet with Jekyll 4.4.1 and Kramdown GFM.\n- Make Docker the documented environment for dependency updates, preview, and production builds.\n- Exclude build-only files from `_site` and document the Zeppelin-to-`zeppelin-site` publication boundary.\n- Remove obsolete third-party analytics, comment, sharing, and feed integrations.\n- Replace two externally hosted graph diagrams with original Apache-licensed SVG diagrams.\n- Preserve Apache Zeppelin\u0027s approved ASF Matomo site ID 69 only in `--safe` production builds.\n- Add a generated-site check for non-ASF embedded resources and unapproved trackers.\n\nThis also prevents the build manifests covered by ZEPPELIN-6431 from being copied into future versioned documentation snapshots. Cleaning historical snapshots remains work in `apache/zeppelin-site`.\n\n### What type of PR is it?\nImprovement\n\n### Todos\n* [x] Upgrade the Jekyll and Ruby toolchain.\n* [x] Document and verify the Docker-only build.\n* [x] Remove legacy integrations and empty Atom/RSS feeds.\n* [x] Replace external documentation images with original local SVG diagrams.\n* [x] Preserve approved ASF Matomo tracking for production docs.\n* [x] Verify generated output and external-resource policy.\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6432\n* Related: https://issues.apache.org/jira/browse/ZEPPELIN-6431\n\n### How should this be tested?\nFrom `docs/`:\n\n```bash\ndocker run --rm \\\n  --user \"$(id -u):$(id -g)\" \\\n  -e HOME\u003d/usr/local/bundle \\\n  -e BUNDLE_FROZEN\u003dtrue \\\n  -v \"$PWD:/docs\" \\\n  -w /docs \\\n  ruby:4.0.6 \\\n  bash -lc \"bundle install \u0026\u0026 bundle exec jekyll build --safe\"\n```\n\nThen:\n\n```bash\ndocker run --rm \\\n  -v \"$PWD:/docs:ro\" \\\n  -w /docs \\\n  ruby:4.0.6 \\\n  ruby check_external_resources.rb _site\n```\n\nThe final verification generated 94 HTML files with Jekyll 4.4.1, emitted no build warnings, retained ASF Matomo site ID 69 only in the safe build, and produced no Atom/RSS or build-manifest output. It also verified that both original SVG diagrams are present in the generated site without the previous GitHub/S3 resource URLs. The full Apache RAT check passed for all 56 reactor modules.\n\n### Screenshots (if appropriate)\nThe replacement diagrams are committed as SVG files and rendered directly by the documentation page; this PR does not change the documentation CSS or page layout.\n\n### Questions:\n* Does the license files need to update? No.\n* Is there breaking changes for older versions? No runtime behavior changes; this affects the documentation build and generated output.\n* Does this needs documentation? `docs/README.md` and `docs/AGENTS.md` are updated.\n\n\n\n\nCloses #5372 from jongyoul/codex/docs-agents-guide.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "c199b4074278316c99e5cc53304aeca3992b5f73",
      "tree": "f7df7456bb34701a66f23856383a0fde0352aeae",
      "parents": [
        "856cf2ad8ec066262b5c0af64db6ec31b2bf64a4"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Thu Aug 13 01:05:56 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 13 01:05:56 2026 +0900"
      },
      "message": "[ZEPPELIN-6638] Time out the React remote entry load\n\n### What is this PR for?\n\n`ReactRemoteLoaderService` settles `loadContainer()` only from the script tag\u0027s `onload` and `onerror`. Neither fires while a request is merely pending, and there is no timer. A `remoteEntry.js` request that the server accepts and never answers therefore leaves the promise pending for as long as the browser keeps the connection open, which is minutes.\n\n`onError` is never called, so the hosts that depend on it never fall back. The paragraph footer keeps an empty mount div instead of restoring `zeppelin-notebook-paragraph-footer`, and the published paragraph renders nothing. Both look like a slow page rather than a failed load.\n\nThis bounds the script load with `environment.reactRemoteLoadTimeoutMs` (10 s, or 0 to disable) and reuses the existing `fail()` path on expiry, which removes the tag and leaves the caches drained so a later mount can retry.\n\nThe chunks that `container.get()` pulls are left alone. They are fetched by the remote\u0027s own webpack runtime, which already bounds them with `output.chunkLoadTimeout` (120 s by default). A second, shorter timer over that path would cut off a multi-megabyte chunk on a slow connection, which is a worse failure than the one being fixed.\n\n### What type of PR is it?\n\nBug Fix\n\n### Todos\n\nNone\n\n### What is the Jira issue?\n\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6638\n\n### How should this be tested?\n\n* Two new Playwright cases in `e2e/tests/notebook/paragraph/react-footer.spec.ts`: one holds `remoteEntry.js` open without ever answering and asserts the Angular footer comes back, one answers after a delay well inside the budget and asserts the React footer still renders. The first fails on master and passes here; verified by setting the budget to 0, which reproduces the current behaviour and makes it fail.\n* The existing abort and delay cases in the same suite, and `e2e/tests/notebook/published/published-paragraph.spec.ts`, for regressions. Chromium, all green.\n* A production build (`npm run build`).\n* A unit spec for the service would be the better home for the timer, but the Angular shell has no test harness on master yet (ZEPPELIN-6566, ZEPPELIN-6567, ZEPPELIN-6637) and this file carries an `\u003cat\u003eInjectable` decorator, which the current setup cannot compile. Left to a follow-up once that lands.\n\n### Screenshots (if appropriate)\n\nNo\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? Yes, the loader section of `projects/zeppelin-react/README.md` is updated in this PR\n\nCloses #5409 from kimyenac/ZEPPELIN-6638.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "856cf2ad8ec066262b5c0af64db6ec31b2bf64a4",
      "tree": "11b588c9da3f6d1e882c36486e853f84bd4329b6",
      "parents": [
        "e887d7c41403d4dcd16114aa361f2097058e7bcf"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Wed Aug 12 23:24:45 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 12 23:24:45 2026 +0900"
      },
      "message": "[ZEPPELIN-6567] Give the Angular shell a self-contained unit test setup\n\n### What is this PR for?\r\nThis PR gives zeppelin-web-angular a self-contained unit test setup for Angular shell code.\r\n\r\nPreviously, the shell unit test path depended on `projects/zeppelin-react` for `Vitest`/`jsdom`. That meant the shell test command crossed a package boundary, the Vitest config could not normally import `vitest/config`, and the spec tsconfig was not usable for real type checking.\r\n\r\nThis PR adds `Vitest`/`jsdom` to the Angular package itself, adds a shell-only Vitest config and spec tsconfig, and wires `test:shell` into the existing npm run lint path so it runs through the Maven/GitHub test phase.\r\n\r\nIt also keeps the Vitest setup file outside `src`, so it is not pulled into production Angular compilation.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6567\r\n\r\n### How should this be tested?\r\nRun from zeppelin-web-angular:\r\n```sh\r\nnpm run test:shell\r\n```\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\n\nCloses #5401 from miinhho/self-contained-angular-shell-test-setup.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "e887d7c41403d4dcd16114aa361f2097058e7bcf",
      "tree": "76b3f9a7ed1654ed4129f2f5ae277b4dbbe13baf",
      "parents": [
        "4728b91e2700dbf2ad014ad2e797e1cfef3342b5"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Wed Aug 12 16:10:01 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 12 15:10:01 2026 +0800"
      },
      "message": "[ZEPPELIN-6528] Handle forbidden interpreter responses in classic UI\n\n### What is this PR for?\n\nApache Shiro 2.0.6 returns HTTP 403 for an authenticated user who lacks a required role. Shiro 1.13.0 returned HTTP 401 for the same authorization denial.\n\nThe classic interpreter page only handled HTTP 401, so a 403 response did not show the permission error toast or redirect the user. This also caused `AuthenticationIT.testAnyOfRolesUser` to fail with `Expected ngToast not found`.\n\nThis PR handles both 401 and 403 responses and adds controller tests covering both statuses.\n\n### What type of PR is it?\n\nBug Fix\n\n### Todos\n\n* [x] Handle HTTP 403 authorization denials in the classic interpreter page\n* [x] Preserve the existing HTTP 401 behavior\n* [x] Add regression tests for both response statuses\n\n### What is the Jira issue?\n\n* https://issues.apache.org/jira/browse/ZEPPELIN-6528\n\n### How should this be tested?\n\n```bash\ncd zeppelin-web\nnpm run karma-test -- --single-run\n```\n\nLocal validation:\n\n* ESLint passed for the changed controller and test.\n* `git diff --check` passed.\n* Karma compiled the application and test bundle successfully, but the browser run could not start locally because Firefox is not installed in the worktree environment.\n\n### Screenshots\n\nN/A\n\n### Questions\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this need documentation? No\n\n\nCloses #5416 from jongyoul/codex/ZEPPELIN-6528-handle-shiro-403.\n\nSigned-off-by: Cheng Pan \u003cchengpan@apache.org\u003e"
    },
    {
      "commit": "4728b91e2700dbf2ad014ad2e797e1cfef3342b5",
      "tree": "5082f5dac0d3bb9dd077be782277fb88c6115970",
      "parents": [
        "2029a3496ecde03a38bb446aa503c10c2bf8a6d5"
      ],
      "author": {
        "name": "Cheng Pan",
        "email": "chengpan@apache.org",
        "time": "Wed Aug 12 14:47:03 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 12 15:47:03 2026 +0900"
      },
      "message": "[ZEPPELIN-6639] Migrate Cassandra interpreter tests to Testcontainers with Cassandra 4.x\n\n## What is this PR for?\n\nThe Cassandra interpreter tests use `cassandra-unit` which embeds Cassandra 3.11.5 in-process. Cassandra 3.x is EOL (unmaintained, archived) and crashes on JDK 17 because `Unsafe.objectFieldOffset()` on hidden classes (lambdas) throws `UnsupportedOperationException` during `PREPARE` statement storage -- a hard JVM restriction no flag can override. This PR migrates the tests to Testcontainers with Cassandra 4.1.3 (the latest maintained 4.1.x), which handles JDK 17 correctly. This is a prerequisite for JDK 17 support.\n\n## What type of PR is it?\n\nImprovement\n\n## What is the Jira issue?\n\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6639\n\n## How should this be tested?\n\n- `cassandra` module: 39 tests pass on JDK 11 and JDK 17 with Docker\n- `./mvnw test -pl cassandra`\n\n## Questions\n\n- Does the licenses file need update? No\n- Is there breaking changes for older versions? No\n- Does this needs documentation? No\n\n## Details\n\n- Replace `cassandra-unit` dependency with `org.testcontainers:cassandra` (`cassandra:4.1.3` image)\n- Add `org.testcontainers:cassandra` to root `pom.xml` dependencyManagement\n- Rewrite `CassandraInterpreterTest` to use `CassandraContainer` instead of `EmbeddedCassandraServerHelper`\n- Load CQL test data via `CqlSession` instead of `CQLDataLoader`\n- Update test expectation HTML files to match Cassandra 4.x table option output:\n  - `additional_write_policy \u003d \u002799p\u0027` (new in 4.x)\n  - `read_repair \u003d \u0027BLOCKING\u0027` (replaces `dclocal_read_repair_chance` + `read_repair_chance`)\n  - `speculative_retry \u003d \u002799p\u0027` (replaces `\u002799PERCENTILE\u0027`)\n  - `compression chunk_length_in_kb \u003d 16` (was 64)\n  - `NoResultWithExecutionInfo.html`: replace hardcoded `localhost:9142` with `TRIED_HOSTS`/`QUERIED_HOSTS` placeholders\n- Normalize `localhost/\u0026lt;unresolved\u0026gt;:port` in test assertions (JDK 17+ `InetSocketAddress.toString()` renders unresolved addresses differently)\n\nAssisted-by: GLM 5.2\n\n\nCloses #5412 from pan3793/ZEPPELIN-6639.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "2029a3496ecde03a38bb446aa503c10c2bf8a6d5",
      "tree": "75fbaa79d67a57b0c1d48d06c5f8a7d62adcd661",
      "parents": [
        "1f80e7a7678cb3d580a49c0637ade7ecc04c9d3c"
      ],
      "author": {
        "name": "Chaiwon Hwang",
        "email": "90598552+uommou@users.noreply.github.com",
        "time": "Wed Aug 12 10:23:07 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 12 10:23:07 2026 +0900"
      },
      "message": "[ZEPPELIN-6503] Update README.md Core features section to reflect current capabilities\n\n### What is this PR for?\r\n\r\nUpdate the `Core features` section in `README.md` to better reflect Apache Zeppelin\u0027s current capabilities.\r\n\r\nThe previous section only mentioned the web-based notebook editor and built-in Apache Spark support. This update highlights multi-language interpreter support, process isolation, visualization, dynamic forms, notebook scheduling, and flexible deployment options.\r\n\r\n### What type of PR is it?\r\n\r\nDocumentation\r\n\r\n### What is the Jira issue?\r\n\r\n[ZEPPELIN-6503](https://issues.apache.org/jira/browse/ZEPPELIN-6503)\r\n\r\n### How should this be tested?\r\n\r\nDocumentation-only change.\r\n\r\n- Reviewed the rendered Markdown content\r\n- Verified the diff with `git diff --check`\r\n\r\n### Screenshots (if appropriate)\r\n\r\nNot applicable.\r\n\r\n### Questions\r\n\r\n- Does the license file need to be updated? No\r\n- Is there breaking API change? No\r\n- Does this need documentation? No additional documentation is required\n\nCloses #5410 from uommou/fix/ZEPPELIN-6503.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "1f80e7a7678cb3d580a49c0637ade7ecc04c9d3c",
      "tree": "5e2060b6c4afcd4f0ade938619b8e9b806d06305",
      "parents": [
        "0e72120aaecaa13993b862fbd8b714cc6e5e2b54"
      ],
      "author": {
        "name": "Lee SuJung",
        "email": "153787023+xhaktm00@users.noreply.github.com",
        "time": "Mon Aug 10 23:58:56 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 23:58:56 2026 +0900"
      },
      "message": "[ZEPPELIN-6556] Personalized mode leaks a non-owner\u0027s paragraph edits into the shared master paragraph\n\n### What is this PR for?\r\nA note can be switched to personalized mode so that each user gets their own copy of a paragraph and one user\u0027s form values and results do not affect another\u0027s.\r\n\r\nHowever, `NotebookService.runParagraph` writes the caller\u0027s `params`, `text`, `title` and `config` into the shared master paragraph *before* it checks whether the note is personalized:\r\n\r\n```java\r\np.setText(text);\r\np.setTitle(title);\r\np.setAuthenticationInfo(context.getAutheInfo());\r\nif (params !\u003d null \u0026\u0026 !params.isEmpty()) {\r\n  p.settings.setParams(params);       // master paragraph\r\n}\r\nif (config !\u003d null \u0026\u0026 !config.isEmpty()) {\r\n  p.mergeConfig(config);              // master paragraph\r\n}\r\n\r\nif (note.isPersonalizedMode()) {\r\n  p \u003d p.getUserParagraph(context.getAutheInfo().getUser());\r\n  ...                                 // the user copy gets the same values\r\n}\r\n```\r\n\r\n`notebook.saveNote(...)` then persists the polluted master. The same ordering exists in `updateParagraph`, and `setParagraphUsingMessage` is worse: its personalized branch re-fetches the master via `note.getParagraph(paragraphId)` instead of resolving the user copy, so it writes the same values into the master twice and never touches the user copy at all.\r\n\r\nSo in personalized mode, a non-owner who edits a dynamic form and runs the paragraph silently overwrites the shared original.\r\n\r\nBecause `Paragraph.userParagraphMap` is transient, the per-user copies do not survive a restart. The corruption stays invisible while the copies exist and surfaces later:\r\n\r\n- after a server restart the user copies are gone and every user sees whatever the last runner wrote\r\n- turning personalized mode off (`Note.clearUserParagraphs`) exposes the polluted master\r\n- a user opening the note for the first time clones the polluted master\r\n\r\n**The fix**: resolve the target paragraph *first* — when the note is personalized, switch to `getUserParagraph(user)` before any write — so the master paragraph is never mutated by another user\u0027s run or update. Applied to `runParagraph`, `updateParagraph` and `setParagraphUsingMessage`. Since the two branches wrote identical values, this also removes the duplicated write blocks.\r\n\r\nThe only caller of `setParagraphUsingMessage` is `spell()`, which now records the spell result on the user copy in personalized mode — the intended behavior — instead of on the shared master.\r\n\r\nNote: `PersonalizeActionsIT.testDynamicFormAction` asserts the correct behavior (a non-owner\u0027s edit must not leak) but was passing against the old server behavior only because a late WebSocket broadcast reverted the typed form value before the run.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Resolve the user paragraph before writing params/text/title/config in `runParagraph`, `updateParagraph` and `setParagraphUsingMessage`\r\n* [x] Fix `setParagraphUsingMessage` re-fetching the master in its personalized branch\r\n* [x] Add a unit test that asserts master paragraph integrity in personalized mode\r\n\r\n### What is the Jira issue?\r\n* [ZEPPELIN-6556](https://issues.apache.org/jira/browse/ZEPPELIN-6556)\r\n\r\n### How should this be tested?\r\nNew test `NotebookServiceTest#testRunParagraphInPersonalizedModeDoesNotPolluteMasterParagraph`: on a personalized note, it runs and then updates a paragraph as `user1` with new params/title, and asserts that the master paragraph\u0027s params and title are unchanged while `getUserParagraph(\"user1\")` picks up the new values.\r\n\r\n```\r\n./mvnw -pl zeppelin-server test -Dtest\u003dNotebookServiceTest -DfailIfNoTests\u003dfalse\r\n```\r\n\r\nResult with the fix: `Tests run: 6, Failures: 0, Errors: 0`.\r\n\r\nManual verification: create a note with `%md echo \"hello, ${name\u003doriginal}\"`, run it, enable personalized mode, log in as a second user, change the form value and run. Then turn personalized mode off (or restart the server): the paragraph must still show `original`.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5360 from xhaktm00/ZEPPELIN-6556.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "0e72120aaecaa13993b862fbd8b714cc6e5e2b54",
      "tree": "365ca4023c21259de91f95081479faec13818e23",
      "parents": [
        "2892d46258c58cafc22767d0e27dfd30da8fd9e5"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Mon Aug 10 23:55:20 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 23:55:20 2026 +0900"
      },
      "message": "[ZEPPELIN-5858] Fix moveNote/saveNote race that duplicates notes\n\n### What is this PR for?\n`moveNote` mutates the folder tree, the `notesInfo` mapping and the notebook repo without holding any lock, while `saveNote` derives its target file name from the path carried by the `Note` object at save time. A save racing with a move therefore writes the note back to its pre-move path, and the same noteId ends up on disk twice. ZEPPELIN-5858 describes exactly this and ships a reproduction; this PR ports that reproduction onto the current API and fixes the race.\n\nReproduced on current master with the ported test (`VFSNotebookRepoWithDelay` extends `VFSNotebookRepo` and injects repo latency, e.g. remote storage):\n\n```\nSaving note 2MXKZT37A to folder_1/note_2MXKZT37A.zpln\nMove note 2MXKZT37A to /folder_2/note\nMove note 2MXKZT37A from /folder_1/note to /folder_2/note\nSaving note 2MXKZT37A to folder_1/note_2MXKZT37A.zpln   \u003c- stale path, resurrects the old file\n\nExpected exactly one .zpln file, but found:\n  [folder_2/note_2MXKZT37A.zpln, folder_1/note_2MXKZT37A.zpln]\n```\n\nThe fix serializes NoteManager\u0027s persistent mutations: `moveNote`, `removeNote` and `moveFolder` now run their tree, mapping and repo mutations inside the monitor `saveNote` already synchronizes on. Save callers and `moveNote` share the cached `Note` instance, so a save that loses the monitor to a concurrent move derives its file name from the already-updated path once it enters — no note is written to its pre-move location. `saveNote`\u0027s existing contract (the `Note` object\u0027s path is authoritative; `addOrUpdateNoteNode` syncs the mapping to it) is deliberately left untouched, since rename-by-save flows like `Notebook.updateNote` and note import depend on it.\n\nTwo deliberate details:\n\n- The fixed lock order in this code base is note `readLock` -\u003e NoteManager monitor, because every save caller runs inside `processNote` holding the note\u0027s readLock. `moveNote` therefore updates the cached note path directly via the note cache instead of calling `processNote` while holding the monitor, and the rename-triggered resave stays outside the monitor and reuses `saveNote`. This keeps the lock order consistent on every path.\n- The rename-triggered resave realigns the reloaded note with the move target before saving: a note evicted from the cache is reloaded from disk at that point, and the on-disk JSON still carries the pre-move name.\n\nVerified the causality both ways: the reproduction test fails with two `.zpln` files for the same noteId on master, passes with this change, and fails again if only the `NoteManager` change is reverted.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] Port the reproduction attached to ZEPPELIN-5858 onto the current NotebookRepo API\n* [x] Serialize NoteManager mutations\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-5858\n\n### How should this be tested?\n`mvn test -pl zeppelin-server -Dtest\u003dNotebookServiceRaceConditionTest` — the test runs `renameNote` and `insertParagraph` concurrently against a delay-injecting `VFSNotebookRepo` subclass, then walks the notebook directory and asserts exactly one `.zpln` file remains. Without the `NoteManager` change it finds the same noteId at both the old and the new path.\n\nRegression: `NoteManagerTest`, `NotebookServiceTest`, `NotebookTest`, `LuceneSearchTest`, `ZeppelinRestApiTest` (86 tests) all pass.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5325 from HwangRock/ZEPPELIN-5858.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "2892d46258c58cafc22767d0e27dfd30da8fd9e5",
      "tree": "a357f50caa75963d9a8798715acb1cec342b8231",
      "parents": [
        "4d02c15e510d8e9874f40284e0008994d56fede1"
      ],
      "author": {
        "name": "chaeyoung kim",
        "email": "152389483+chelsseeey@users.noreply.github.com",
        "time": "Mon Aug 10 10:26:38 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 10:26:38 2026 +0900"
      },
      "message": "[ZEPPELIN-6628] Add an internal-link check to the docs build\n\n### What is this PR for?\r\n\r\nAdds a CI job that builds the Jekyll site under `docs/` and validates its internal links with html-proofer, and fixes the broken links that turning the check on exposes.\r\n\r\nThe docs link to each other with relative paths, and nothing validates them today. No workflow builds the site at all, so a wrong path passes `quick`, `core` and `frontend` alike and only surfaces once the site is published. Three such links exist on master.\r\n\r\n`JB.BASE_PATH` has to be accounted for. Template links are rendered with that prefix (`/docs/0.13.0-SNAPSHOT/...`), which exists only on the published site, so an unadjusted run reports every templated link as broken — 322 internal links, all of them failing. The job reads `BASE_PATH` out of `_config.yml` and strips it with `--swap-urls`, so links resolve against the built tree and a version bump does not silently break the job.\r\n\r\nScope is deliberately narrow: `--disable-external` skips external URLs and `--no-check-internal-hash` skips anchor fragments, both of which fail for reasons outside this repository and would make the job flaky. `--allow-missing-href` keeps the `\u003ca name\u003d\"...\"\u003e` anchors the docs use as link targets from being reported as errors.\r\n\r\nThe job is report-only for now (`continue-on-error: true`), as the issue asks. Broken links show up in the log without blocking a merge; the comment in the workflow says when to drop that.\r\n\r\nThe change has two parts.\r\n\r\n**Fix the broken internal links**\r\n\r\n- `docs/setup/operation/configuration.md` — raw HTML link, one `../` short. From `/setup/operation/` it resolved to `/setup/usage/other_features/customizing_homepage.html`; the page is at `/usage/...`.\r\n- `docs/setup/deployment/yarn_install.md` — `install.html` resolved to `/setup/deployment/install.html`; the install guide is at `/quickstart/install.html`. Matches how `upgrading.md` and `flink_and_spark_cluster.md` already link it.\r\n- `docs/development/helium/writing_spell.md` — the URL is wrapped in literal quotes inside the markdown link, so it renders as `href\u003d\"%22https://www.npmjs.com/%22\"`. Not mentioned on the Jira issue, but master does not pass the check without it.\r\n\r\n**Add the check**\r\n\r\nNew `.github/workflows/docs.yml`, triggered only on changes under `docs/**` and on the workflow itself.\r\n\r\n### What type of PR is it?\r\n\r\nImprovement\r\n\r\n### Todos\r\n\r\nNone. Dropping `continue-on-error` is deliberately left for a follow-up, as the issue asks; the workflow carries a comment saying so.\r\n\r\n### What is the Jira issue?\r\n\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6628\r\n\r\n### How should this be tested?\r\n\r\nThe new job runs on this PR, since it touches `docs/**`.\r\n\r\nLocally, using the container from `docs/README.md`:\r\n\r\n```bash\r\ndocker run --rm -v \"$PWD/docs:/docs\" -w /docs ruby:3.3.5 bash -c \u0027\r\n  bundle install \u0026\u0026\r\n  bundle exec jekyll build --safe -d _site \u0026\u0026\r\n  gem install html-proofer -v 5.2.2 --no-document \u0026\u0026\r\n  BASE_PATH\u003d$(ruby -ryaml -e \u0027\"\u0027\"\u0027puts(YAML.load_file(\"_config.yml\")[\"JB\"][\"BASE_PATH\"] || \"\")\u0027\"\u0027\"\u0027) \u0026\u0026\r\n  htmlproofer _site --root-dir _site --checks Links --disable-external \\\r\n    --no-enforce-https --no-check-internal-hash --allow-missing-href \\\r\n    --swap-urls \"^${BASE_PATH}:\"\u0027\r\n```\r\n\r\nOn master, this reports the three failures above. With this PR applied it reports none:\r\n\r\n```\r\nChecking 321 internal links\r\nRan on 94 files!\r\nHTML-Proofer finished successfully.\r\n```\r\n\r\nReverting any one of the three link fixes brings back that failure, and only that one, which confirms the check detects each of them.\r\n\r\n### Screenshots (if appropriate)\r\n\r\nNo\r\n\r\n### Questions:\r\n\r\n* Does the license files need to update? No. No new dependency ships with the site — html-proofer is installed in the CI job only, and `docs/Gemfile` is untouched. The one new file lives under `.github/`, which the rat profile excludes; `./mvnw apache-rat:check -Prat` passes.\r\n* Is there breaking changes for older versions? No. Documentation and CI only.\r\n* Does this needs documentation? No.\r\n\n\nCloses #5395 from chelsseeey/ZEPPELIN-6628-docs-internal-link-check.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "4d02c15e510d8e9874f40284e0008994d56fede1",
      "tree": "37dfab7c4c6448deceeaa5aad9694cf555b52dfa",
      "parents": [
        "a403bed905eca3653be08f051ae05021031aa203"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Mon Aug 10 09:21:18 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 09:21:18 2026 +0900"
      },
      "message": "[ZEPPELIN-6575] Reclaim idle interpreters on the server with a per-setting timeout\n\n### What is this PR for?\nAn interpreter setting cannot have its own idle timeout today, and worse, trying to give it one fails silently.\n\nIdle reclaim is decided inside the interpreter process by `TimeoutLifecycleManager`, which reads its threshold from the configuration map the server pushes over Thrift when the process starts. That map is built by `ZeppelinConfiguration#getCompleteConfiguration()`:\n\n```java\nfor (ConfVars c : ConfVars.values()) {\n  if (getString(c) !\u003d null) {\n    completeConfiguration.put(c.getVarName(), getString(c));\n  }\n}\n```\n\nIts key set is closed over the `ConfVars` enum, so an interpreter setting property has no slot to travel in. An operator can put the threshold property on a single interpreter\u0027s settings, it is stored, it is shown again when the form is reopened - and the process still starts with the global value. No error, no warning.\n\nSo the threshold is effectively all-or-nothing across every interpreter, which does not match how they differ in cost. A Spark interpreter holding tens of gigabytes of cluster memory is worth reclaiming aggressively; a JDBC interpreter that only keeps a few connections open is usually worth keeping. Today an operator who enables idle reclaim gets one number for both.\n\nThis moves the decision to the server, which already knows the per-setting value:\n\n- `ManagedInterpreterGroup` records when the group was last used. The three hooks mirror the ones `RemoteInterpreterServer` already calls in-process (`interpret`, `getProgress`, `getStatus`), so no new notion of activity is introduced. `getStatus` matters most: `RemoteScheduler.JobStatusPoller` calls it while a paragraph runs, which is what keeps a long-running paragraph from having its interpreter pulled out from under it.\n- `IdleInterpreterReclaimer` walks `getAllInterpreterGroup()` on a timer, resolves the threshold from the owning interpreter setting (falling back to the global property), and closes the group by reusing `ManagedInterpreterGroup.close()`. It reads in-memory state only and never calls `isAlive()`/`isRunning()`, whose cost depends on the launcher - a socket connect with a 1s timeout for docker, an unbounded kube-apiserver round trip for k8s - and this runs over every group on a timer.\n- A group whose process is still launching is skipped. The handle field is assigned before `start()`, while the idle clock has been running since the group was created, so without this a launch slower than the threshold gets killed while coming up. Spark on YARN takes minutes to launch, so this is not hypothetical.\n\n**No new configuration property, and nothing changes unless asked for.** This follows the existing lifecycle manager class property, which already expresses whether idle reclaim is wanted at all. Its `NullLifecycleManager` default means an existing deployment sees no change whatsoever; `TimeoutLifecycleManager` now also enables server-driven reclaim. Any other implementation is left untouched. `ZeppelinConfiguration#getLifecycleManagerClass()` had no caller before this change.\n\nAn interpreter setting overrides the threshold by carrying the same property name, where `0` or below means never reclaimed. This is opt-in per interpreter: a setting that carries nothing keeps following the global threshold exactly as before, so the JDBC interpreter above is still reclaimed on the global schedule until an operator marks it as exempt. What the change adds is the ability to say it at all.\n\n**`TimeoutLifecycleManager` is kept, not replaced.** It still runs in the interpreter process, because that is what shuts a process down if the Zeppelin server itself exits unexpectedly and can no longer reclaim anything. It is handed the same threshold resolved here rather than the global one, so the two sides agree instead of one of them shutting a process down on the wrong schedule. Closing a group twice cannot happen either: if the process shuts itself down it unregisters, which removes the group from `getAllInterpreterGroup()`; if the server closes the group first, the process and its scheduler are gone.\n\nThat fallback is intentionally given up for one case only - a setting the operator marked as never reclaimed (`0`), whose process receives `Long.MAX_VALUE` and therefore will not self-terminate either. `TimeoutLifecycleManager` has no way to express \"never\" and would read a threshold of `0` as \"shut down at the next check\".\n\n### What type of PR is it?\nFeature\n\n### Todos\n* [x] - Track last-used time per interpreter group on the server\n* [x] - Close groups idle beyond the threshold, reusing `ManagedInterpreterGroup.close()`\n* [x] - Resolve the threshold per interpreter setting, falling back to the global property\n* [x] - Keep the in-process fallback consistent by pushing the resolved threshold to the process\n* [x] - Skip groups whose process is still launching\n* [x] - Unit tests, including guards against probing and against reclaiming a launching group\n* [x] - Document the per-interpreter threshold in `docs/usage/interpreter/overview.md` and `conf/zeppelin-site.xml.template`\n\n### What is the Jira issue?\n* [ZEPPELIN-6575](https://issues.apache.org/jira/browse/ZEPPELIN-6575), a sub-task of [ZEPPELIN-6568](https://issues.apache.org/jira/browse/ZEPPELIN-6568)\n\n### How should this be tested?\n`IdleInterpreterReclaimerTest` (9 tests) covers both directions of the override, the launching guard, the no-probe guard, threshold resolution, and that the default lifecycle manager changes nothing.\n\n```bash\nexport JAVA_HOME\u003d$(/usr/libexec/java_home -v 11)\n./mvnw package -pl zeppelin-server --am \\\n  -Dtest\u003dIdleInterpreterReclaimerTest,TimeoutLifecycleManagerTest -DfailIfNoTests\u003dfalse\n```\n\nThe two override tests fail before the change, because the per-setting value never reaches the process:\n\n```\nperSettingThresholdReclaimsEarlierThanTheGlobalOne\n  the group should be reclaimed after the per setting threshold of 10s\n  \u003d\u003d\u003e expected: \u003c0\u003e but was: \u003c1\u003e\n\nperSettingThresholdCanOptOutOfAShortGlobalThreshold\n  the setting opted out of reclaim, so the short global threshold must not apply\n  \u003d\u003d\u003e expected: \u003c1\u003e but was: \u003c0\u003e\n```\n\n`aGroupBeingLaunchedIsNotReclaimed` fails without the launching guard, and `scanNeverProbesTheInterpreterProcess` fails if the scan is written with `isAlive()`/`isRunning()`.\n\nLocal runs, all passing:\n\n| Scope | Result |\n|---|---|\n| `org.apache.zeppelin.interpreter.**` (19 classes, includes recovery and launcher tests) | pass |\n| `notebook`, `rest`, `service`, `socket`, `server`, `notebook.repo` (39 classes, 318 tests) | pass |\n| `TimeoutLifecycleManagerTest` (existing idle reclaim behaviour) | pass, no regression |\n| `./mvnw clean org.apache.rat:apache-rat-plugin:check -Prat` | `Unapproved: 0` |\n\nManual steps on a running server. This uses two of the lightweight built-in interpreters, `md` (markdown) and `sh` (shell), so that two interpreters run side by side under one server and one global threshold:\n\n1. In `zeppelin-site.xml` set the lifecycle manager class to `TimeoutLifecycleManager`, the global threshold to `10s`, and the check interval to `5s`.\n2. On the `md` interpreter setting only, add the threshold property with the value `0` to mark it as never reclaimed. Leave the `sh` setting untouched so that it follows the global 10s.\n3. Run one `%md` paragraph and one `%sh` paragraph, then leave the note idle.\n\nEach interpreter setting gets its own process, and each process logs the threshold it was handed:\n\n```\nlogs/zeppelin-interpreter-md-shared_process-*.log\n  TimeoutLifecycleManager is started with checkInterval: 5000, timeoutThreshold: 9223372036854775807\n\nlogs/zeppelin-interpreter-sh-shared_process-*.log\n  TimeoutLifecycleManager is started with checkInterval: 5000, timeoutThreshold: 10000\n```\n\nBefore this change both processes were handed the global `10000` and both were shut down after 10s of idle time; the `0` on the `md` setting had no effect at all. Now only `sh` is reclaimed, and the server log records why:\n\n```\nlogs/zeppelin-*.log\n  Reclaiming interpreter group sh-shared_process of interpreter setting sh:\n    idle for 11603ms which exceeds its threshold of 10000ms\n```\n\n`ps` confirmed the `sh` process was gone about 15s after its last use, while the `md` process was still running after 33s of idle time. Both processes kept the lifecycle manager class the operator configured; only the threshold they received differed.\n\nNot verified locally, left to CI and to deployments that have the runtimes: the docker, k8s and yarn launchers. The reclaim path does not call into a launcher - it neither probes nor launches, only closes - so the exposure is limited to `close()`, which the existing restart endpoint already uses.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No. The two new files carry the ASF header and `apache-rat-plugin:check` reports no unapproved files.\n* Is there breaking changes for older versions? No. With the default `NullLifecycleManager` nothing is scheduled and no configuration is overridden for the interpreter process, so an untouched deployment behaves exactly as before.\n* Does this needs documentation? Yes, and it is included. `docs/usage/interpreter/overview.md` gains a \"Per interpreter idle threshold\" section, and the descriptions in `conf/zeppelin-site.xml.template` are extended. No values in the template were changed.\n\n\nCloses #5358 from big-cir/ZEPPELIN-6575.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "a403bed905eca3653be08f051ae05021031aa203",
      "tree": "ddae4197c7536c65409bc76e80e229195232f607",
      "parents": [
        "a7458a8a5ecb456e6e1cb8b5537775cc0695eed2"
      ],
      "author": {
        "name": "YooJung Huh",
        "email": "gjenfwo@gmail.com",
        "time": "Mon Aug 10 02:20:38 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 10 02:20:38 2026 +0900"
      },
      "message": "[ZEPPELIN-6436] Fix stale module names and test commands in embedding search documentation\n\n### What is this PR for?\r\n`docs/embedding-search.md` still referenced the `zeppelin-zengine` module, which was merged into `zeppelin-server` in ZEPPELIN-6355 before the embedding search feature was added in ZEPPELIN-6411. As a result, the implementation paths and the `mvn test -pl zeppelin-zengine` commands in the doc no longer match the current repository layout and the test commands fail as written. This PR updates the stale references so the documentation is accurate and the test commands actually run.\r\n\r\n\r\n### What type of PR is it?\r\nDocumentation\r\n\r\n### Todos\r\n- [x]  Replace `zeppelin-zengine` references with `zeppelin-server` in implementation paths\r\n- [x] Update `mvn test -pl` commands to target `zeppelin-server`\r\n- [x] Verify referenced source/test files exist at the corrected paths\r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6436](https://issues.apache.org/jira/browse/ZEPPELIN-6436)\r\n\r\n### How should this be tested?\r\nConfirm no stale references remain: `rg -n \"zeppelin-zengine\" docs/embedding-search.md`\r\n\u003cimg width\u003d\"600\" height\u003d\"40\" alt\u003d\"image\" src\u003d\"https://github.com/user-attachments/assets/bbc621ba-dbd8-4e59-b2d7-bde56243219f\" /\u003e\r\n\r\nOptionally \r\nConfirm the corrected paths exist in the repo:\r\n`zeppelin-server/src/main/java/org/apache/zeppelin/search/EmbeddingSearch.java`\r\n`zeppelin-server/src/test/java/org/apache/zeppelin/search/EmbeddingSearchTest.java`\r\n`zeppelin-server/src/test/java/org/apache/zeppelin/search/LuceneSearchTest.java`\r\n\r\nRun the corrected commands to confirm they work:\r\n`mvn test -pl zeppelin-server -Dtest\u003dLuceneSearchTest`\r\n`ZEPPELIN_EMBEDDING_TEST\u003dtrue mvn test -pl zeppelin-server -Dtest\u003dEmbeddingSearchTest`\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? This PR is the documentation fix.\n\nCloses #5408 from gjenfwo/ZEPPELIN-6436-fix-embedding-search-docs.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "a7458a8a5ecb456e6e1cb8b5537775cc0695eed2",
      "tree": "93ea86c4d030c6dfff54540e84975478bac0ba36",
      "parents": [
        "427bf3aa5c8010cdbdb04b256c4e0bf0d78f054d"
      ],
      "author": {
        "name": "YeonKyung Ryu",
        "email": "80758099+celinayk@users.noreply.github.com",
        "time": "Sun Aug 09 23:55:30 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 23:55:30 2026 +0900"
      },
      "message": "[ZEPPELIN-6459] Align Docker image logging configuration and documentation with Log4j2\n\n### What is this PR for?\r\nDocker-related scripts and docs still referenced Log4j 1.x style `log4j.properties`                                                                               files, and the reporter suspected these were obsolete leftovers from a Log4j2                                                                                       migration. Investigation showed the opposite: Zeppelin\u0027s default SLF4J binding is                                                                                   `slf4j-reload4j`, so `log4j.properties` is still the primary logging config, while                                                                                  `log4j2.properties` exists only for Flink\u0027s bundled real Log4j2 core — both are                                                                                    required, not obsolete.                                                                                                                                             \r\n                                                                                                                                                                      \r\nThe real bug found: `DockerInterpreterProcess` (the `DockerInterpreterLauncher`                                                                                     feature) uploads `log4j.properties` and `log4j_yarn_cluster.properties` from the host                                                                               \r\nto the interpreter container, but never `log4j2.properties`, even though                                                                                            `bin/common.sh` looks for it via `-Dlog4j.configurationFile` for every local                                                                                        interpreter process. This PR adds it to the transferred file list, aligns                                                                                           `docs/quickstart/docker.md`\u0027s file list with the code, documents why                                                                                                `scripts/docker/zeppelin/bin/Dockerfile` needs all 4 log4j* files (so they aren\u0027t                                                                                   mistaken for duplicates again), and clarifies in                                                                                                                   `docs/setup/deployment/docker.md` that `ZEPPELIN_IN_DOCKER` applies to the all-in-one                                                                               image, not the split `zeppelin-server`/`zeppelin-interpreter` images.\r\n\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n\r\n### Todos\r\n * [x] Add missing `log4j2.properties` to `DockerInterpreterProcess`\u0027s container file                                                                               transfer list                                                                                                                                                     \r\n  * [x] Sync `docs/quickstart/docker.md`\u0027s transferred-file list with the code                                                                                        \r\n  * [x] Document why `scripts/docker/zeppelin/bin/Dockerfile` ships 4 log4j* files                                                                                    \r\n  * [x] Clarify `ZEPPELIN_IN_DOCKER` scope in `docs/setup/deployment/docker.md`\r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6459](https://issues.apache.org/jira/browse/ZEPPELIN-6459)\r\n\r\n### How should this be tested?\r\n  * No existing unit test covers `DockerInterpreterProcess#copyRunFileToContainer`                                                                                    \r\n    (it\u0027s private and untested), so no automated test was added for the transfer list                                                                                 \r\n    itself; existing `DockerInterpreterProcessTest` (6 tests) still passes unchanged.                                                                                 \r\n  * Manually verified: built the exact tar archive `DockerInterpreterProcess` produces                                                                                \r\n    using the same `TarUtils`/`TarFileEntry` production classes with the fixed                                                                                        \r\n    `copyFiles` entries, injected it into a real Alpine container via the same                                                                                        \r\n    upload-tar-then-extract mechanism `deployToContainer` uses, and confirmed                                                                                         \r\n    `log4j.properties`, `log4j2.properties`, and `log4j_yarn_cluster.properties` all                                                                                  \r\n    land at the expected `conf/` path inside the container with content identical                                                                                     \r\n    (byte-for-byte `diff`) to the host source files.\r\n\r\n### Screenshots (if appropriate)\r\n  N/A (docs/config change, no UI impact)\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation?  Yes — `docs/quickstart/docker.md` and                                                                                             `docs/setup/deployment/docker.md` updated as part of this PR\r\n\n\nCloses #5371 from celinayk/ZEPPELIN-6459.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "427bf3aa5c8010cdbdb04b256c4e0bf0d78f054d",
      "tree": "d02f40c5375c77665a6eedeaffb102f045b16e93",
      "parents": [
        "2147d79acbca4d06d87e52b06e41228e17e04e8d"
      ],
      "author": {
        "name": "gyowoo1113",
        "email": "58352333+gyowoo1113@users.noreply.github.com",
        "time": "Sun Aug 09 23:20:18 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 23:20:18 2026 +0900"
      },
      "message": "[ZEPPELIN-6543] Handle invokeMethod serialization failure as InterpreterRPCException\n\n### What is this PR for?\r\nThis PR follows up on ZEPPELIN-6467 / PR #5312.\r\n\r\nFollowing PR #5312, `Resource.serializeObject()` propagates serialization failures as `IOException`. As a result, `RemoteInterpreterEventServer.invokeMethod()` can receive an exception while re-serializing a remote resource invocation result. The existing handler logged the exception and returned a null `ByteBuffer`, causing the generated Thrift client to report a missing result instead of preserving the original serialization failure.\r\n\r\nThe Jira issue identified this behavior through code analysis, but the server-side deserialize-and-re-serialize failure path had not yet been reproduced.\r\n\r\nThis PR adds a regression test using a serializable object that succeeds during the initial serialization and fails during the server-side second serialization. It then changes `invokeMethod()` to propagate the failure as `InterpreterRPCException`, allowing the original error message to reach the caller instead of being converted into an unrelated Thrift missing-result error.\r\n\r\nThe behavior for successfully serialized results is unchanged.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Reproduce the server-side deserialize-and-re-serialize failure path with a regression test\r\n* [x] Propagate serialization failures as `InterpreterRPCException`\r\n* [x] Verify that the propagated exception contains the original failure message\r\n\r\n### What is the Jira issue?\r\n[[ZEPPELIN-6543](https://issues.apache.org/jira/browse/ZEPPELIN-6543)]\r\n\r\n### How should this be tested?\r\n`./mvnw test -pl zeppelin-server -Dtest\u003dRemoteInterpreterEventServerTest` passes successfully.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n* Code inspection suggests that `Resource.serializeObject()` may return `null` when the result is not serializable, but this path is not covered by the regression test in this PR. Should this case also be handled in this PR, or should it be addressed separately?\n\nCloses #5349 from gyowoo1113/ZEPPELIN-6543-handle-invoke-method-serialization-failure.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "2147d79acbca4d06d87e52b06e41228e17e04e8d",
      "tree": "e83576ed1779e671245199308db947b251b70d04",
      "parents": [
        "149f51fed7d9d3fb4000cd08ade00b34ee09b42c"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Sun Aug 09 23:15:46 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 23:15:46 2026 +0900"
      },
      "message": "[ZEPPELIN-6548] Use specific exceptions for Spark Scala fallback detection\n\n### What is this PR for?\r\n\r\nThis PR refines exception types in `SparkInterpreterLauncher` when the fallback Spark Scala version detection validates the `SPARK_HOME/jars` layout.\r\n\r\nPreviously, `detectSparkScalaVersionByReplClass(...)` threw generic `Exception` for expected validation failures such as missing or duplicate `spark-repl` jars, or an unsupported `spark-repl` Scala suffix. This PR replaces those generic throw sites with more specific exception types while keeping the existing messages and caller behavior unchanged.\r\n\r\nMissing or duplicate `spark-repl` jars now throw `IOException`, and an unrecognized Scala suffix now throws `IllegalArgumentException`.\r\n\r\nThis PR is a follow-up to [ZEPPELIN-6464](https://issues.apache.org/jira/browse/ZEPPELIN-6464)\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6548\r\n\r\n### How should this be tested?\r\n- Build and run the module tests:\r\n```\r\n./mvnw test -pl zeppelin-server --am\r\n```\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\n\nCloses #5340 from miinhho/refactor/specific-exception-in-spark-scala-fallback.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "149f51fed7d9d3fb4000cd08ade00b34ee09b42c",
      "tree": "a95bb9e78b87198c4c27622e5ac24fc34d26ec3b",
      "parents": [
        "3d71dfef07cbef158e5544c46783cdec0cb32290"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Sun Aug 09 23:09:50 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 23:09:50 2026 +0900"
      },
      "message": "[ZEPPELIN-6129] Restore parallel paragraph execution for concurrent interpreters\n\n### What is this PR for?\n\nParagraphs of the same interpreter cannot run in parallel, even when the interpreter is configured for concurrent execution (e.g. a presto JDBC interpreter with `zeppelin.jdbc.concurrent.use\u003dtrue`).\n\nThis is a regression from [ZEPPELIN-5900] (#4582). That PR switched `RemoteScheduler`\u0027s executor to a per-scheduler `newSingleThreadExecutor` so that `RemoteSchedulerTest.testAbortOnPending` became deterministic. Before it, `RemoteScheduler` was constructed with the shared multi-threaded pool from `SchedulerFactory.getExecutor()`, and every interpreter could submit paragraphs to the remote side concurrently.\n\nScheduling is two-tier: the server-side `RemoteScheduler` is a proxy, and each interpreter\u0027s remote-side `getScheduler()` (FIFO vs Parallel) decides the real concurrency. Once the server side became single-threaded, it gated every interpreter behind a single in-flight submission, so a remote `ParallelScheduler` never received a second job to run. The JDBC concurrency flag was read on the remote side but the server side never let a second paragraph through.\n\nThe fix restores an interpreter-neutral pool on the server side and delegates parallelism back to the remote scheduler:\n\n- `RemoteScheduler`: paragraph mode now builds a bounded `newFixedThreadPool` sized from `zeppelin.interpreter.connection.poolsize` (default 100, matching the RPC connection pool). Note mode keeps `newSingleThreadExecutor` to preserve in-note paragraph ordering. The JDBC-specific `zeppelin.jdbc.concurrent.*` gate is removed — it only helped JDBC and left Shell / Markdown / MongoDB / Neo4j / Cassandra / Flink SQL and other always-parallel interpreters serialized on the server side.\n- The paragraph/note blocking-wait in `runJobInScheduler` is untouched. It is what keeps FIFO interpreters (Python, Spark, ...) serial and note mode ordered: a FIFO interpreter\u0027s second job never reaches RUNNING remotely, so the wait still serializes it.\n- Cancellation hardening for the now-multithreaded pool: `Job.aborted` is `volatile`, and `AbstractScheduler.runJob`\u0027s abort gate runs under `synchronized(runningJob)`, so a cancel arriving right before run reliably skips execution instead of racing.\n- `JDBCUserConfigurations`: `paragraphIdStatementMap` is a `ConcurrentHashMap` and `cancelStatement` null-checks the statement, so a cancel arriving before the statement is registered is a no-op rather than an NPE.\n\nNet effect: interpreters whose remote `getScheduler()` returns a `ParallelScheduler` (Shell, Markdown, MongoDB, Neo4j, Cassandra, Flink SQL, JDBC with concurrency on, ...) regain parallel paragraph execution; FIFO interpreters and note mode stay serial.\n\n### What type of PR is it?\nBug Fix\n\n### What is the Jira issue?\n[ZEPPELIN-6129](https://issues.apache.org/jira/browse/ZEPPELIN-6129)\n\n### How should this be tested?\n\nUnit / integration:\n\n```\n./mvnw test -pl zeppelin-interpreter,jdbc,zeppelin-server -am \\\n  -Dtest\u003dRemoteSchedulerTest,AbstractSchedulerAbortRaceTest,JobTest,JDBCUserConfigurationsTest,JDBCInterpreterTest\n```\n\n- `RemoteSchedulerTest#testParallelExecution_bothJobsRunConcurrently` — two jobs reach RUNNING simultaneously through `RemoteScheduler`; fails against the single-thread executor, passes with the neutral pool.\n- `RemoteSchedulerTest#testAbortOnPending_noteModeSerial` — note mode still serializes and aborts a queued job before it runs.\n- `AbstractSchedulerAbortRaceTest` — the abort gate and cancel share the job monitor (latch-driven, deterministic).\n- `JDBCUserConfigurationsTest` — cancel-before-register is a no-op, not an NPE.\n\nEnd-to-end (verified locally against a real server; the IT itself is kept out of this PR to keep CI light): two `%sh` paragraphs each running `sleep 5`, triggered via the async REST endpoint `POST /api/notebook/job/{noteId}/{paragraphId}`, with no concurrency property set (Shell is a `ParallelScheduler` by default). Status was polled and the two paragraphs were observed RUNNING at the same time:\n\n```\nboth paragraphs observed RUNNING simultaneously at +3425ms\ntotal elapsed until both FINISHED: 8287ms\n```\n\nSerial execution would be ~10000ms (2 x sleep 5), and a single-thread pool can never reach simultaneous RUNNING because the second paragraph stays PENDING until the first finishes. The overlap at +3425ms and the ~8.3s wall-clock confirm the two paragraphs ran in parallel.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5332 from HwangRock/ZEPPELIN-6129.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "3d71dfef07cbef158e5544c46783cdec0cb32290",
      "tree": "975aab7fd78a8eb59d32ad41208ef1ca88f28939",
      "parents": [
        "206b6a319dd4e30bf8c5df7331847f440724fff0"
      ],
      "author": {
        "name": "HyeonUk Kang",
        "email": "43662405+hyunw9@users.noreply.github.com",
        "time": "Sun Aug 09 22:58:29 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 22:58:29 2026 +0900"
      },
      "message": "[ZEPPELIN-6555] Avoid deadlock in ManagedInterpreterGroup.close() by not holding the group lock while closing session interpreters\n\n### What is this PR for?\r\n`ManagedInterpreterGroup.close()` can deadlock with a concurrent `RemoteInterpreter.open()` because the two paths take the same two monitors in the opposite order.\r\n\r\nTwo monitors are involved: the interpreter-group monitor and an individual interpreter\u0027s monitor.\r\n\r\n- `open()` takes the interpreter monitor first (`synchronized(this)`) and then the group monitor (via `getOrCreateSession()` and the angular-registry push).  Order: interpreter → group.\r\n- `close(String)` is a `synchronized` method, so it holds the group monitor while it spawns the per-interpreter close threads and `join()`s them. Each close thread runs `interpreter.close()`, which takes the interpreter monitor. Order: group → interpreter.\r\n\r\nSo when an interpreter is opened while its session is concurrently closed (for example, restarting or shutting down an interpreter while a paragraph on that session is still starting up), the two orders form a circular wait.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Stop holding the group monitor while closing session interpreters in `close(String)`\r\n* [x] Keep only the session-map removal and last-session teardown under the lock\r\n* [x] Add regression test `ManagedInterpreterGroupTest#close_doesNotDeadlockWithConcurrentOpen`\r\n\r\n### What is the Jira issue?\r\n[[ZEPPELIN-6555]](https://issues.apache.org/jira/browse/ZEPPELIN-6555)\r\n\r\n### How should this be tested?\r\n- Added a deterministic regression test,`ManagedInterpreterGroupTest#close_doesNotDeadlockWithConcurrentOpen`.\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? - No\r\n* Is there breaking changes for older versions? - No\r\n* Does this needs documentation? - No\r\n\n\nCloses #5329 from hyunw9/ZEPPELIN-6555.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "206b6a319dd4e30bf8c5df7331847f440724fff0",
      "tree": "4b20282e43cf533807a4fd8a97ac7d28d222bd71",
      "parents": [
        "9b8d82beb9eb884568fad896ee8f5b28a4c716f6"
      ],
      "author": {
        "name": "HyeonUk Kang",
        "email": "43662405+hyunw9@users.noreply.github.com",
        "time": "Sun Aug 09 22:53:41 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 22:53:41 2026 +0900"
      },
      "message": "[ZEPPELIN-6208] Enable DuckDB support in JDBC Interpreter by excluding incompatible default properties\n\n What is this PR for?\r\n\r\n  The JDBC interpreter forwards all of an interpreter\u0027s prefixed properties (default.*) straight to the JDBC driver when opening a connection. Many of these keys are consumed by Zeppelin itself or by the DBCP connection pool — e.g. driver, url, precode, statementPrecode,\r\n  completer.ttlInSeconds, validationQuery, maxIdle — and are not valid JDBC connection properties.\r\n\r\n  Lenient drivers (PostgreSQL, MySQL) silently ignore unknown properties, so this went unnoticed. But strict drivers reject the connection outright. For example, DuckDB fails with:\r\n\r\n  SQLException: Invalid Input Error: The following options were not recognized:\r\n                completer.ttlInSeconds, url, driver, maxIdle\r\n\r\n  This currently makes it impossible to use DuckDB (and other strict drivers such as MS SQL Server) with the JDBC interpreter.\r\n\r\n  Until now this was worked around with a driver-specific whitelist that only applied when the driver class was Presto/Trino (PRESTO_PROPERTIES). That approach is hard to maintain: every new strict driver needs its own if branch and allow-list, and it also strips any legitimate driver\r\n  property the user added but that wasn\u0027t on the list.\r\n\r\n  This PR replaces that with a generic, driver-agnostic deny-list:\r\n\r\n  - Introduces NON_DRIVER_PROPERTIES, a single source of truth listing only Zeppelin-internal and DBCP pool keys (user/password are deliberately kept, since they are standard JDBC properties).\r\n  - Adds toDriverProperties(), which returns a filtered copy of the properties handed to the driver, leaving the original untouched (the previous Presto code mutated the shared per-user Properties in place — a latent bug).\r\n  - Removes the Presto/Trino special-case branch and the PRESTO_PROPERTIES whitelist; the generic filter subsumes it.\r\n  - Adds an optional escape hatch, zeppelin.jdbc.driver.excludeProperties (comma-separated), so operators can exclude additional keys for future drivers without a code change.\r\n\r\n  Result: DuckDB, MS SQL Server, Trino/Presto, and any future strict driver work through one consistent rule, while genuine driver properties (e.g. SSL, useSSL, sslmode) still pass through unchanged.\r\n\r\n  What type of PR is it?\r\n\r\n  Bug Fix\r\n\r\n  Todos\r\n\r\n  - [x] Replace Presto/Trino whitelist with a generic internal-property deny-list\r\n  - [x] Keep user/password and arbitrary driver properties (e.g. SSL) flowing to the driver\r\n  - [x] Add unit tests for the filtering logic\r\n  - [x] Add end-to-end tests against real strict drivers (DuckDB embedded, Trino)\r\n\r\n| Property setting (1) | Property setting (2) |\r\n  |:---:|:---:|\r\n  | \u003cimg width\u003d\"2507\" height\u003d\"963\" alt\u003d\"스크린샷 2026-06-25 오후 9 20 23\" src\u003d\"https://github.com/user-attachments/assets/9c32bab8-d6d5-4096-b90a-5fa59e434509\" /\u003e | \u003cimg width\u003d\"2083\" height\u003d\"139\" alt\u003d\"스크린샷 2026-06-25 오후 9 20 29\" src\u003d\"https://github.com/user-attachments/assets/2e0d2320-59eb-4efb-b28d-0f9bf5e7bc5f\" /\u003e |\r\n\r\n  **2. Result — Before / After**\r\n\r\n  | Before — DuckDB connection error | After — connected successfully |\r\n  |:---:|:---:|\r\n  | \u003cimg width\u003d\"2462\" height\u003d\"206\" alt\u003d\"before-duckdb-error\" src\u003d\"https://github.com/user-attachments/assets/9b204002-9373-44a1-8d9b-1e41da30e4f6\" /\u003e | \u003cimg width\u003d\"2475\" height\u003d\"517\" alt\u003d\"after-success\" src\u003d\"https://github.com/user-attachments/assets/417141ca-f780-4e58-8f55-0c32f9d6102c\" /\u003e\r\n  \r\n\r\n  What is the Jira issue?\r\n\r\n  - [ZEPPELIN-6208](https://issues.apache.org/jira/browse/ZEPPELIN-6208)\r\n\r\n  How should this be tested?\r\n\r\n  Automated tests added in JDBCInterpreterTest:\r\n\r\n  - testToDriverProperties — internal/pool keys are removed; user, password, and arbitrary driver props (SSL) are kept; the original Properties is not mutated.\r\n  - testToDriverPropertiesWithUserDefinedExcludes — zeppelin.jdbc.driver.excludeProperties strips additional user-specified keys.\r\n  - testDuckDbConnectionWithInternalProperties — end-to-end: configures the interpreter with internal keys present and runs CREATE/INSERT/SELECT against an embedded DuckDB (no server needed). Fails on the old code, passes here.\r\n  - testTrinoConnectionWithInternalProperties — end-to-end against a real Trino coordinator; auto-skipped via assumeTrue when none is reachable on localhost:8080.\r\n\r\n  mvn -pl jdbc -am test -Dtest\u003dJDBCInterpreterTest\r\n\r\n  Manual: add a JDBC interpreter with default.driver\u003dorg.duckdb.DuckDBDriver, default.url\u003djdbc:duckdb:, add the org.duckdb:duckdb_jdbc dependency in the interpreter settings, leave an internal key such as default.completer.ttlInSeconds\u003d120, and run a query — it now connects successfully.\r\n\r\n\r\n\r\n  Questions:\r\n\r\n  - Does the license files need to update? - X\r\n  - Is there breaking changes for older versions? - X\r\n  - Does this need documentation? - Optional \n\nCloses #5276 from hyunw9/ZEPPELIN-6208.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "9b8d82beb9eb884568fad896ee8f5b28a4c716f6",
      "tree": "1f6b409326084876170490b53f5725e972a0e67d",
      "parents": [
        "560a808e3eab694654ab74c678ff1f1883c5c83c"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Sun Aug 09 22:36:06 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 22:36:06 2026 +0900"
      },
      "message": "[ZEPPELIN-6635] Remove unnecessary git add from lint-staged configuration\n\n### What is this PR for?\r\nThis PR removes unnecessary `git add` commands from the `lint-staged` configuration in `zeppelin-web-angular/package.json`.\r\n\r\nThe project currently uses `lint-staged` v15, and lint-staged has automatically re-staged task modifications since v10. Keeping explicit `git add` entries is outdated and produce warnings, so this cleanup leaves the existing ESLint and Prettier tasks unchanged while relying on lint-staged\u0027s built-in staging behavior.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6635\r\n\r\n### How should this be tested?\r\n  * Run the frontend pre-commit workflow with staged TypeScript/JavaScript/JSON/CSS/HTML changes and confirm `lint-staged` still runs ESLint/Prettier successfully.\r\n  * Confirm no lint-staged warning is emitted for using `git add` in task configuration.\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5402 from miinhho/remove-git-add-from-lint-staged.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "560a808e3eab694654ab74c678ff1f1883c5c83c",
      "tree": "1046173f027fec538ee3c115920ff9eda54c5d90",
      "parents": [
        "e1d96d65d6c9314039a73d485d11e28d52f7b133"
      ],
      "author": {
        "name": "김다은 (Daeun Kim)",
        "email": "150661115+dani1552@users.noreply.github.com",
        "time": "Sun Aug 09 21:43:22 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 21:43:22 2026 +0900"
      },
      "message": "[ZEPPELIN-6507] Return empty list from FileInterpreter.completion()\n\n### What is this PR for?\r\n`FileInterpreter.completion()` returns `null` rather than an empty list. Per *Effective Java* Item 54, methods that return a collection should never return `null`, since it forces every caller to add a special-case null check.\r\n\r\nIn practice this base implementation is not reached today: the only concrete subclass, `HDFSFileInterpreter`, overrides `completion()` with a real implementation. However, if a future `FileInterpreter` subclass omits that override, the `null` would propagate through the completion call chain, which does not perform null checks.\r\n\r\nThis PR changes the base implementation to return `Collections.emptyList()` and adds a unit test that pins the contract.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n* [x] - Return `Collections.emptyList()` from `FileInterpreter.completion()`\r\n* [x] - Add `testCompletionReturnsEmptyListInsteadOfNull` to `FileInterpreterTest`\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6507\r\n\r\n### How should this be tested?\r\n* `mvn test -pl file -Dtest\u003dFileInterpreterTest`\r\n* `TestFileInterpreter`, the test double already present in `FileInterpreterTest`, does not override `completion()`, so the new test exercises the base implementation directly.\r\n* All 5 tests in `FileInterpreterTest` pass locally.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\n\nCloses #5394 from dani1552/ZEPPELIN-6507.\n\nSigned-off-by: ParkGyeongTae \u003cgyeongtae@apache.org\u003e"
    },
    {
      "commit": "e1d96d65d6c9314039a73d485d11e28d52f7b133",
      "tree": "0b7e16efeacb03dc1c5d9d42b39adc967ce67bef",
      "parents": [
        "6baf0f9ad1a9a464b6a15a6ca069572c02b5672f"
      ],
      "author": {
        "name": "DONGHOON LEE",
        "email": "125895298+move-hoon@users.noreply.github.com",
        "time": "Sun Aug 09 21:05:19 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 21:05:19 2026 +0900"
      },
      "message": "[ZEPPELIN-6457] Extract shared Python ZeppelinContext helpers for PySpark and PyFlink\n\n### What is this PR for?\n\nPySpark and PyFlink currently define their `ZeppelinContext` subclasses separately in the classic Python and IPython bootstrap resources, even though the implementations are effectively the same for each backend.\n\nThis PR moves the PySpark and PyFlink implementations into the shared `zeppelin_context.py` resource and reuses them from both bootstrap paths.\n\nBackend-specific behavior remains unchanged:\n\n* PySpark handles Spark `DataFrame` objects through `_jdf`.\n* PyFlink handles Flink `Table` objects through `_j_table`.\n* PyFlink retains support for the `stream_type` argument.\n* Other object types fall back to `PyZeppelinContext.show()`.\n* `IPySparkZeppelinContext` and `IPyFlinkZeppelinContext` remain available as compatibility aliases.\n\nNo new dependencies are introduced.\n\n### What type of PR is it?\n\nRefactoring\n\n### Todos\n\n* [x] Move the PySpark ZeppelinContext implementation to the shared resource\n* [x] Move the PyFlink ZeppelinContext implementation to the shared resource\n* [x] Reuse the shared implementations from Python and IPython bootstraps\n* [x] Keep the existing IPython class names as compatibility aliases\n* [x] Verify Spark and Flink interpreter packaging\n* [x] Verify PySpark `z.show(DataFrame)` behavior\n\n### What is the Jira issue?\n\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6457\n\n### How should this be tested?\n\nThe following checks passed successfully:\n\n```bash\n./mvnw test \\\n  -pl python \\\n  -Dtest\u003dPythonInterpreterTest#testBackendZeppelinContextsAvailable \\\n  -DfailIfNoTests\u003dfalse \\\n  -Dmaven.gitcommitid.skip\u003dtrue\n```\n\nResult: 1 test passed.\n\n```bash\nPYSPARK_PYTHON\u003d\"$(command -v python3.12)\" \\\nPYSPARK_DRIVER_PYTHON\u003d\"$(command -v python3.12)\" \\\n./mvnw test \\\n  -pl spark/interpreter \\\n  --am \\\n  -Pspark-3.5 \\\n  -Pspark-scala-2.12 \\\n  -Dtest\u003dPySparkInterpreterTest#testPySpark \\\n  -Dsurefire.failIfNoSpecifiedTests\u003dfalse \\\n  -Dmaven.gitcommitid.skip\u003dtrue\n```\n\nResults:\n\n* `PySparkInterpreterTest#testPySpark` passed.\n* Existing ScalaTest suite: 18 tests passed.\n* `z.show(DataFrame)` was exercised successfully.\n\n```bash\n./mvnw package \\\n  -pl spark/interpreter \\\n  --am \\\n  -Pspark-3.5 \\\n  -Pspark-scala-2.12 \\\n  -DskipTests \\\n  -Dmaven.gitcommitid.skip\u003dtrue\n```\n\nResult: 12-module reactor build succeeded.\n\n```bash\n./mvnw package \\\n  -pl flink/flink-scala-2.12 \\\n  --am \\\n  -Pflink-1.20 \\\n  -DskipTests \\\n  -Dmaven.gitcommitid.skip\u003dtrue\n```\n\nResult: 13-module reactor build succeeded.\n\nThe generated Spark and Flink interpreter JARs were also verified to contain the shared context resource and the corresponding classic and IPython bootstrap resources.\n\n`git diff --check` also passes.\n\n### Screenshots (if appropriate)\n\nNot applicable. This PR does not change the user interface.\n\n### Questions\n\n* Do the license files need to be updated? No.\n* Are there breaking changes for older versions? No. The existing IPython context names remain available as compatibility aliases.\n* Does this need documentation? No. There are no user-facing behavior or configuration changes.\n\n\n\nCloses #5405 from move-hoon/ZEPPELIN-6457-python-context.\n\nSigned-off-by: ParkGyeongTae \u003cgyeongtae@apache.org\u003e"
    },
    {
      "commit": "6baf0f9ad1a9a464b6a15a6ca069572c02b5672f",
      "tree": "62bdfb752fdfdd8618eccf3c37e290c1d22b8e7c",
      "parents": [
        "8595f2a148832862377b5638a7925e1850d38c2d"
      ],
      "author": {
        "name": "Gyeongtae Park",
        "email": "gyeongtae@apache.org",
        "time": "Sun Aug 09 19:45:26 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 19:45:26 2026 +0900"
      },
      "message": "[ZEPPELIN-6528] Upgrade Apache Shiro from 1.13.0 to 2.0.6\n\n### What is this PR for?\r\n\r\nUpgrades Apache Shiro from 1.13.0 to 2.0.6, the current stable release line with active security patches. Shiro 2.x strengthens default password hashing (Argon2id instead of MD5) and provides Jakarta EE 10 support, which aligns with the jakarta.* namespace already in use by this project.\r\n\r\nThis PR also resolves a transitive BouncyCastle version conflict introduced by shiro-crypto-hash:2.0.6 pulling in bcprov-jdk18on:1.82, and fixes the two compile-breaking API changes between Shiro 1.x and 2.x.\r\n\r\n### What type of PR is it?\r\n\r\nImprovement\r\n\r\n### Todos\r\n\r\n* [x] Bump shiro.version 1.13.0 → 2.0.6 in pom.xml\r\n* [x] Bump bouncycastle.version 1.80 → 1.82 to resolve DependencyConvergence conflict\r\n* [x] Replace removed DefaultLdapContextFactory with JndiLdapContextFactory in ActiveDirectoryGroupRealm\r\n* [x] Update StringUtils import to org.apache.shiro.lang.util in LdapRealm\r\n* [x] Update LifecycleUtils import to org.apache.shiro.lang.util in AbstractShiroTest and ShiroAuthenticationServiceTest\r\n\r\n### What is the Jira issue?\r\n\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6528\r\n\r\n### How should this be tested?\r\n\r\n1. Build zeppelin-server module:\r\n   ./mvnw compile -pl zeppelin-server -am -DskipTests\r\n2. Run Shiro-related unit tests:\r\n   ./mvnw test -pl zeppelin-server -Dtest\u003d\"ShiroAuthenticationServiceTest,LdapRealmTest,LdapRealmDnInjectionTest,AnyOfRolesUserAuthorizationFilterTest\"\r\n3. Manually verify form login, LDAP authentication flows remain functional.\r\n\r\n### Screenshots (if appropriate)\r\n\r\nN/A\r\n\r\n### Questions:\r\n\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No — API-level changes are confined to internal realm and test infrastructure classes.\r\n* Does this needs documentation? No\n\nCloses #5293 from ParkGyeongTae/ZEPPELIN-6528.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "8595f2a148832862377b5638a7925e1850d38c2d",
      "tree": "78e2501fab5e186112bb63f8e052e02fe6561702",
      "parents": [
        "894186578ebdce07c7b1b48fe6c6b9a1ee7cc393"
      ],
      "author": {
        "name": "Yerin Lee",
        "email": "91695537+yxinot@users.noreply.github.com",
        "time": "Sun Aug 09 17:04:18 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 17:04:18 2026 +0900"
      },
      "message": "[ZEPPELIN-6461] Fix InterruptedException handling in recoverRunningParagraphs\n\n### What is this PR for?\r\n In `Notebook.recoverRunningParagraphs()`, the `InterruptedException` caught from `thread.join()` was handled with `e.printStackTrace()`, which bypasses the project\u0027s Log4j2 configuration. Additionally, the thread interrupt status was not restored, preventing callers from observing the interruption. This PR replaces `e.printStackTrace()` with SLF4J logging and adds `Thread.currentThread().interrupt()` to restore the interrupt status.\r\n\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Replace `e.printStackTrace()` with `LOGGER.warn()` (SLF4J)\r\n* [x] Restore thread interrupt status with `Thread.currentThread().interrupt()`\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6461\r\n\r\n### How should this be tested?\r\n  ```bash\r\n  ./mvnw test -pl zeppelin-server -Dtest\u003dNotebookTest -DfailIfNoTests\u003dfalse\r\n```\r\n\r\n### Questions:\r\n  - Does the license files need to update? No\r\n  - Is there breaking changes for older versions? No\r\n  - Does this needs documentation? No\r\n\r\n\n\nCloses #5393 from yxinot/ZEPPELIN-6461-fix-interrupted-exception-handling.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "894186578ebdce07c7b1b48fe6c6b9a1ee7cc393",
      "tree": "33299f39205716e4acda29e1195d6d30dd51f031",
      "parents": [
        "7d840af6d46869da1c3fefd819480e55c6bfe19d"
      ],
      "author": {
        "name": "uommou",
        "email": "90598552+uommou@users.noreply.github.com",
        "time": "Sun Aug 09 17:02:13 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 17:02:13 2026 +0900"
      },
      "message": "[ZEPPELIN-6491] Remove Google Analytics from generated version docs\n\n### What is this PR for?\r\n\r\nThis PR removes Google Analytics from generated version documentation by disabling the analytics provider in the Jekyll configuration.\r\n\r\nPreviously, running `bundle exec jekyll build --safe` generated HTML containing Google Analytics scripts because the `google_universal` analytics provider was enabled. This change disables the provider, removes the Zeppelin-specific Google Analytics tracking IDs, and adds a verification step to the documentation deployment process to help ensure future generated version documentation remains compliant with the ASF website privacy policy.\r\n\r\n### What type of PR is it?\r\n\r\nBug Fix\r\n\r\n### Todos\r\n\r\n* [x] Disable the Google Analytics provider in `docs/_config.yml`\r\n* [x] Remove the Zeppelin-specific Google Analytics tracking IDs\r\n* [x] Add a verification step to `docs/README.md`\r\n* [x] Validate that generated HTML contains no Google Analytics references\r\n\r\n### What is the Jira issue?\r\n\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6491\r\n\r\n### How should this be tested?\r\n\r\n1. Build the documentation.\r\n\r\n```bash\r\ncd docs\r\nbundle exec jekyll build --safe\r\n```\r\n\r\n2. Verify that no Google Analytics references exist in the generated HTML.\r\n\r\n```bash\r\n(\r\n  grep -rnE --include\u003d\u0027*.html\u0027 \\\r\n    \"google-analytics\\.com|googletagmanager\\.com|analytics\\.js|ga\\.js|UA-[0-9]\" \\\r\n    _site/\r\n  case $? in\r\n    0) echo \"FAIL: analytics found\"; exit 1 ;;\r\n    1) echo \"PASS: no Google Analytics references found in generated HTML\" ;;\r\n    *) echo \"ERROR: scan failed\"; exit 2 ;;\r\n  esac\r\n)\r\n```\r\n\r\n**Validation results**\r\n\r\n* ✅ Documentation build completed successfully.\r\n\r\n```text\r\nConfiguration file: /Users/chaiwonhwang/Projects/zeppelin/docs/_config.yml\r\nSource: /Users/chaiwonhwang/Projects/zeppelin/docs\r\nDestination: /Users/chaiwonhwang/Projects/zeppelin/docs/_site\r\nGenerating...\r\ndone in 0.602 seconds.\r\n```\r\n\r\n* ✅ Generated HTML validation passed.\r\n\r\n```text\r\nPASS: no Google Analytics references found in generated HTML\r\n```\r\n\r\n* ✅ Spot-checked the generated `index.html` and a nested documentation page.\r\n* ✅ Confirmed that the analytics include renders no Google Analytics script while normal local assets remain intact.\r\n\r\n### Screenshots (if appropriate)\r\n\r\nN/A\r\n\r\nValidation results are included above.\r\n\r\n### Questions:\r\n\r\n* Does the license files need to update?\r\n\r\nNo.\r\n\r\n* Is there breaking changes for older versions?\r\n\r\nNo.\r\n\r\nThis change only affects future generated version documentation. Existing published documentation in ASF SVN is not modified by this PR.\r\n\r\n* Does this needs documentation?\r\n\r\nYes.\r\n\r\n`docs/README.md` has been updated to document the verification step before deploying generated documentation.\r\n\r\n\n\nCloses #5398 from uommou/fix/ZEPPELIN-6491.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "7d840af6d46869da1c3fefd819480e55c6bfe19d",
      "tree": "6b0c3196d717b093d3849ee2a1b4e380d12e3fed",
      "parents": [
        "03de344818b8153a8ab017da91475d53e91c5dbf"
      ],
      "author": {
        "name": "백형준",
        "email": "138356797+vividbaek@users.noreply.github.com",
        "time": "Sun Aug 09 15:49:28 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 15:49:28 2026 +0900"
      },
      "message": "[ZEPPELIN-6596] Improve editor fallback logging\n\n  ## What is this PR for?\r\n\r\n  Improve warning logs emitted when `InterpreterSettingManager#getEditorSetting` falls back to the default editor.\r\n\r\n  The previous logs only recorded `e.getMessage()`, which could be null and did not preserve the stack trace. The updated logs include the relevant note, interpreter group, or interpreter name together with the throwable.\r\n\r\n  The existing `DEFAULT_EDITOR` fallback behavior is unchanged. Paragraph text is not logged because it may contain notebook code or sensitive information.\r\n\r\n  ## What type of PR is it?\r\n\r\n  Bug Fix\r\n\r\n  ## What is the Jira issue?\r\n\r\n  https://issues.apache.org/jira/browse/ZEPPELIN-6596\r\n\r\n  ## How should this be tested?\r\n\r\n  ```bash\r\n  ./mvnw test -pl zeppelin-server \\\r\n    -Dtest\u003dInterpreterSettingManagerTest\r\n\r\n  Result:\r\n\r\n  Tests run: 12, Failures: 0, Errors: 0, Skipped: 0\r\n  BUILD SUCCESS\n\nCloses #5396 from vividbaek/ZEPPELIN-6596-editor-fallback-logging.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "03de344818b8153a8ab017da91475d53e91c5dbf",
      "tree": "c6fdae06ef41c96b9e8ecffdb66476cc2663ffa8",
      "parents": [
        "ddb8bc6f35cdc6babd69150c447223a4068dd53a"
      ],
      "author": {
        "name": "minjcho",
        "email": "117441212+minjcho@users.noreply.github.com",
        "time": "Sun Aug 09 15:42:59 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 09 15:42:59 2026 +0900"
      },
      "message": "[ZEPPELIN-6153] Add display_name to the kernelspec when exporting to ipynb\n\n### What is this PR for?\r\n\r\nExporting a Zeppelin note to ipynb produces a `kernelspec` with only `language` and `name`:\r\n\r\n```java\r\nJsonObject kernelspecJson \u003d new JsonObject();\r\nkernelspecJson.addProperty(\"language\", \"scala\");\r\nkernelspecJson.addProperty(\"name\", \"spark2-scala\");\r\n```\r\n\r\nThe nbformat schema requires `kernelspec.display_name`, so renderers that validate the schema — GitHub in particular — refuse to display the exported notebook. The import side already models the field (`nbformat/Kernelspec.java` has `display_name`); only the export path in `JupyterUtil.getNbformat()` omits it.\r\n\r\nThis PR writes `\"display_name\": \"Zeppelin\"` into the exported kernelspec, the default suggested in the JIRA issue. The value is kept as a constant (`JupyterUtil.KERNEL_DISPLAY_NAME`) and `Kernelspec` gains getters following the pattern of the sibling nbformat classes (`Metadata`, `Nbformat`), so the new round-trip test can assert on the deserialized object. The test exports `spark_example_notebook.zpln`, reads the result back, and checks the kernelspec carries both `name` and `display_name`.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Write `display_name` into the exported kernelspec\r\n* [x] Expose `Kernelspec` fields through getters\r\n* [x] Pin the behaviour with a round-trip test\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6153\r\n\r\n### How should this be tested?\r\n\r\n```bash\r\n./mvnw test -pl zeppelin-jupyter -Dtest\u003dJupyterUtilTest -DfailIfNoTests\u003dfalse\r\n```\r\n\r\n`Tests run: 5, Failures: 0, Errors: 0, Skipped: 0`\r\n\r\nTo verify end-to-end: export any note to ipynb and push it to a GitHub repository — the notebook now renders instead of showing \"Invalid Notebook\".\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\n\nCloses #5397 from minjcho/ZEPPELIN-6153.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "ddb8bc6f35cdc6babd69150c447223a4068dd53a",
      "tree": "e0595aaa0368b615beb5d5e4cecc664ea9da2421",
      "parents": [
        "f988eef9fe9a2853988193c7572c3b01d554441c"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Sat Aug 08 19:54:29 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Aug 08 19:54:29 2026 +0900"
      },
      "message": "[MINOR] Prevent WebSocket tickets from being logged\n\n### What is this PR for?\n\nThis fixes CVE-2026-44614, where the WebSocket bearer ticket could be written to server or browser diagnostic logs in plaintext.\n\nThe login and security ticket endpoints no longer log their complete ticket-bearing responses. Server-side WebSocket handling now logs only non-secret operation, principal, success, and error type metadata instead of the complete message, payload, or exception details. The active Angular SDK and classic UI likewise log only operation/principal metadata rather than complete WebSocket messages.\n\nTicket response bodies, authentication behavior, and the WebSocket wire protocol remain unchanged. Both clients still attach the bearer ticket to outbound WebSocket frames, but no longer copy it or the complete payload to the browser console.\n\n### What type of PR is it?\n\nHot Fix\n\n### Todos\n\n* [x] Remove ticket-bearing REST response logging\n* [x] Remove raw WebSocket message logging at DEBUG, TRACE, and ERROR\n* [x] Remove ticket-bearing WebSocket message logging from both browser clients\n* [x] Add regression coverage for login, `/api/security/ticket`, WebSocket failures, and classic-client console logging\n\n### What is the Jira issue?\n\nNot applicable. This addresses [CVE-2026-44614](https://lists.apache.org/thread/zlphtbzb8p2sr604597kldpjhhqktsbz).\n\n### How should this be tested?\n\n* `./mvnw -pl zeppelin-server --am -Dtest\u003dSecurityRestApiTest,NotebookServerLoggingTest,NotebookServerTest -Dsurefire.failIfNoSpecifiedTests\u003dfalse -Dmaven.gitcommitid.skip\u003dtrue test`\n  * 27 tests passed with no failures, errors, or skips.\n* `cd zeppelin-web \u0026\u0026 npm run karma-test`\n  * 184 tests passed, including the two new WebSocket console regression tests.\n* `cd zeppelin-web-angular \u0026\u0026 npm run build-project:sdk`\n  * SDK build passed.\n* Focused ESLint and Prettier checks passed for both changed clients.\n* A built-SDK sentinel smoke test confirmed that ticket and payload remain in the transmitted message but are absent from browser console arguments.\n* Apache RAT passed for `zeppelin-server`, `zeppelin-web-angular`, and `zeppelin-web` with no unapproved licenses.\n* `git diff --check apache/master...HEAD`\n\nThe standalone `checkstyle:check` command reports the same existing baseline on clean `apache/master` and this branch: 1,795 repository-wide violations and 103 violations when restricted to the original server files. No violation is reported on a line added or modified by this PR.\n\n### Screenshots (if appropriate)\n\nNot applicable.\n\n### Questions:\n\n* Does the license files need to update? No.\n* Is there breaking changes for older versions? No.\n* Does this needs documentation? No.\n\n\nCloses #5388 from jongyoul/codex/cve-2026-44614-ticket-log-redaction.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "f988eef9fe9a2853988193c7572c3b01d554441c",
      "tree": "f009346480c2784bc2637ea2fed0c57d62ff8f50",
      "parents": [
        "4998576589b94d6236ed156c049371ad902ef184"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Fri Aug 07 12:43:40 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 07 12:43:40 2026 +0900"
      },
      "message": "[ZEPPELIN-6521] Preserve withCredentials on HTTP requests in production builds\n\n### What is this PR for?\n\nIn production builds the interceptor re-clones from the original `httpRequest` when it adds `X-Requested-With`, discarding the `withCredentials: true` clone made one line earlier. `clone()` inherits from whatever it was cloned from (`update.withCredentials ?? this.withCredentials`), so the production request goes out with the default `false`.\n\n```diff\n       let httpRequestUpdated \u003d httpRequest.clone({ withCredentials: true });\n       if (environment.production) {\n-        httpRequestUpdated \u003d httpRequest.clone({ setHeaders: { \u0027X-Requested-With\u0027: \u0027XMLHttpRequest\u0027 } });\n+        httpRequestUpdated \u003d httpRequestUpdated.clone({ setHeaders: { \u0027X-Requested-With\u0027: \u0027XMLHttpRequest\u0027 } });\n       }\n```\n\nTwo things the ticket does not cover. First, `BaseUrlService` builds the REST base from `location`, so every call to Zeppelin\u0027s own API is same-origin and the browser attaches cookies whether or not the flag is set; the flag has no reachable effect on those calls today. The classic UI\u0027s equivalent service remaps the port when the UI is served from the grunt dev server (`zeppelin-web/src/components/base-url/base-url.service.js:26-29`), which is what made `withCredentials` meaningful there, and the new UI has no such path. So this is a correctness fix — the interceptor now applies both of its settings consistently across builds, the way the classic UI does (`zeppelin-web/src/app/app.js:78` and `:161-163`) — rather than a behaviour fix for API traffic. The second is the subject of the next section.\n\n### Scope and related issues\n\n**Third-party URL fetches go through this interceptor too, and this change narrows what they can reach.** `NoteImportComponent` passes a user-supplied URL straight to `HttpClient` (`note-import.component.ts:49`), so the \"import note from URL\" request carries the same `withCredentials` and `X-Requested-With` as a call to Zeppelin\u0027s own API. A browser rejects a credentialed cross-origin response whose `Access-Control-Allow-Origin` is `*`, and that wildcard is what public file hosts serve.\n\nMeasured in Chromium against local servers reproducing each CORS configuration, with the `raw.githubusercontent.com` preflight response checked directly:\n\n| target host | dev build | production today | production after this PR |\n|---|---|---|---|\n| rejects `X-Requested-With` at preflight — `raw.githubusercontent.com` answers the preflight with 403 | blocked | blocked | blocked |\n| allows `X-Requested-With`, serves `Access-Control-Allow-Origin: *` | blocked | works | blocked |\n\nOnly the second row changes, and it changes production to match what development already does, which is what this ticket asks for.\n\nThe underlying problem is that the interceptor does not distinguish Zeppelin\u0027s own API from an arbitrary URL. The classic UI handles it by overriding `withCredentials: false` for exactly this request (`zeppelin-web/src/components/note-import/note-import.controller.js:95-97`); the new UI has no equivalent. That is a separate defect which predates this ticket and already breaks the feature in development builds today.\n\nScoping the interceptor so that `withCredentials` and `X-Requested-With` are applied only to Zeppelin\u0027s own API would resolve it, and would not change anything this PR does for API calls. I have not filed a ticket for it yet — I would rather hear whether that scoping belongs in this PR or in a follow-up.\n\n### What type of PR is it?\n\nBug Fix\n\n### Todos\n\n* [x] - Derive the production clone from the already-credentialed request\n* [x] - Confirm `X-Requested-With` is still added in production builds\n* [x] - Confirm development builds are unaffected\n\n### What is the Jira issue?\n\n* [ZEPPELIN-6521](https://issues.apache.org/jira/browse/ZEPPELIN-6521)\n\n### How should this be tested?\n\nThere is no unit-test runner for this app to add a spec to: the `zeppelin` project in `angular.json` declares only `build`, `serve`, `extract-i18n` and `lint`, and `zeppelin-web-angular/src` contains no `.spec.ts`. A Playwright test is also a poor fit here, because the local suite runs against `ng serve` (`playwright.config.js:16`), where `environment.production` is `false` and the affected branch never executes — such a test would pass with or without this change unless run in CI mode. The change was verified three other ways instead.\n\n**1. Lint**\n\n```\ncd zeppelin-web-angular \u0026\u0026 npm run lint\n```\n\nExit 0. 15 pre-existing `member-ordering` warnings in `projects/zeppelin-visualization`, none in the changed file; `lint:react` clean; `prettier --check` reports all files formatted.\n\n**2. `HttpRequest.clone()` inheritance, using the real class**\n\nRunning both the old and the new form of the production branch through Angular\u0027s real `HttpRequest` class:\n\n```\ndevelopment branch    withCredentials\u003dtrue   X-Requested-With\u003d(none)\nproduction, before    withCredentials\u003dfalse  X-Requested-With\u003dXMLHttpRequest\nproduction, after     withCredentials\u003dtrue   X-Requested-With\u003dXMLHttpRequest\n```\n\n**3. Production bundle in a real browser**\n\n`ng build --configuration production` twice — once with this commit and once with it reverted, changing nothing else — serving `dist/zeppelin` statically and instrumenting the `XMLHttpRequest.prototype.withCredentials` setter. `BaseUrlService` derives the REST base from `location`, so the app issues its normal bootstrap calls against the static server; they 404, but Angular assigns `withCredentials` before `send()`, which is what is being observed.\n\n```\n                      API requests   withCredentials assignments   X-Requested-With\nbefore this commit    4              []                            XMLHttpRequest\nafter  this commit    4              [true, true, true, true]      XMLHttpRequest\n```\n\n`X-Requested-With` is present in both runs, which confirms the production branch really executed and that the change does not drop the header.\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No — see \"Scope and related issues\" for the one behaviour that changes for third-party URL fetches\n* Does this needs documentation? No\n\n\nCloses #5377 from big-cir/ZEPPELIN-6521.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "4998576589b94d6236ed156c049371ad902ef184",
      "tree": "2856a680b39e3c99daa260452f2bcf326b957e55",
      "parents": [
        "3faf553a532df600f4d9b7544e833b3390d1c51c"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Fri Aug 07 12:42:26 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 07 12:42:26 2026 +0900"
      },
      "message": "[ZEPPELIN-3798] Fix wrong link to Dynamic Form docs on Zeppelin Context webpage\n\n### What is this PR for?\nThe two \"Dynamic Form\" links on the Zeppelin Context page point to `../usage/dynamic_form/intro.html`. The page itself is served from `/usage/other_features/`, so that relative path resolves to `/usage/usage/dynamic_form/intro.html` and returns 404. This is still reproducible on the published docs (see the link below). The fix is `../dynamic_form/intro.html`, which is how sibling pages such as `other_features/customizing_homepage.md` link to `../display_system/`.\n\nWhile I was there I audited every relative `.html` link in `docs/` and in the navigation sidebar and found three more broken targets, fixed in the second commit:\n\n* `index.md` and `_navigation.html` link the Notebook Storage entries to `setup/storage/storage.html`, but the file is `notebook_storage.md`. The fragments were wrong too: the docs are rendered with redcarpet, which does not emit heading ids, so the only usable anchors on that page are its explicit `\u003ca name\u003d\"...\"\u003e` tags (`Git`, `S3`, `Azure`, `GCS`, `OSS`, `MongoDB`). This one is visible on every docs page because it is in the sidebar.\n* `usage/interpreter/overview.md` links to `../development/writing_zeppelin_interpreter.html`, which resolves to `/usage/development/`. It needs one more level up.\n* `pleasecontribute.md` links to `development/howtocontributewebsite.html`, which is now `development/contribution/how_to_contribute_website.html`.\n\nAfter this change every relative `.html` link in `docs/` and in the navigation sidebar resolves to an existing page. Happy to split the second commit out into its own JIRA if you prefer to keep this PR to the reported issue only.\n\n### What type of PR is it?\nBug Fix / Documentation\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-3798\n\n### How should this be tested?\nDocs only, no code change. The broken link can be seen on the published docs at https://zeppelin.apache.org/docs/0.12.0/usage/other_features/zeppelin_context.html (the \"Dynamic Form\" links in the body, not the sidebar one), and the Notebook Storage entries in the left sidebar of any docs page 404 as well.\n\nI verified the fix by resolving every relative link in `docs/` against the file tree and confirming each target file exists, and by checking that the anchors used for `notebook_storage.html` are present in that page.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5387 from kimyenac/ZEPPELIN-3798.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "3faf553a532df600f4d9b7544e833b3390d1c51c",
      "tree": "ec2122057104fadd39df4711b43f0627e3bd8a52",
      "parents": [
        "b90e68634b0f2b6e389a84925ea0657457253a9f"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Fri Aug 07 00:22:23 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Aug 07 00:22:23 2026 +0900"
      },
      "message": "[ZEPPELIN-6533] Apply the notebook search term after the paragraph views exist\n\n### What is this PR for?\nThe notebook component reads the `term` query param in `ngOnInit`, which runs before `\u003cat\u003eViewChildren` resolves and before the note arrives over the WebSocket. The initial term was applied to a paragraph query list that did not exist yet, and nothing re-applied it once the paragraphs rendered, so opening a note through a `?term\u003d...` deep link (for example clicking a notebook search result) never highlighted the matching text.\n\nThis keeps the term on the notebook component and re-applies it in `ngAfterViewInit` and whenever the paragraph query list changes. The code editor keeps the term as well, because Monaco loads asynchronously and would otherwise ignore a term that arrived before the editor was ready.\n\nThe guard suggested in the issue (`listOfNotebookParagraphComponent?.forEach(...)`) is already on master, so `onParagraphSearch` does not throw today. The access stays guarded here.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] - Apply the search term once the paragraph views exist\n* [x] - Apply the search term once the Monaco editor is ready\n* [x] - Add an e2e regression test for the `term` deep link\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6533\n\n### How should this be tested?\n* Automated: `e2e/tests/notebook/search/editor-search.spec.ts` gains \"highlights the term carried by a deep link when the notebook opens\". Run it with `npm run e2e:fast -- tests/notebook/search/editor-search.spec.ts` in `zeppelin-web-angular`. The new test fails on master (0 highlights) and passes with this change; the rest of the spec and the notebook keyboard spec stay green.\n* Manual: create a note, put `alpha target beta target gamma target` in a paragraph, then open `/#/notebook/\u003cnoteId\u003e?term\u003dtarget` coming from another page. Every occurrence of `target` is highlighted. The same applies when clicking a result on the notebook search page, which navigates with `paragraph` and `term` query params.\n\n### Screenshots (if appropriate)\nBefore: nothing is highlighted when the note opens through the deep link.\nAfter: the three `target` occurrences are highlighted.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5378 from kimyenac/ZEPPELIN-6533.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "b90e68634b0f2b6e389a84925ea0657457253a9f",
      "tree": "65139447c7fd9f6257cabb8426ed1315c4460bfb",
      "parents": [
        "07cf67087516e16c3d1c6e31716c956f6654f33e"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Thu Aug 06 17:12:05 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 17:12:05 2026 +0900"
      },
      "message": "[ZEPPELIN-6599] Stop treating the user list search text as LDAP filter and regex syntax\n\n### What is this PR for?\n\n`GET /api/security/userlist/{searchText}` interprets the client-supplied search text as syntax in two places. This PR fixes both.\n\n**1. LDAP search filters**\n\n`ShiroAuthenticationService` builds the LDAP search filter by string concatenation, in `getUserList(DefaultLdapRealm, String, int)` and `getUserList(LdapRealm, String, int)`. The filter metacharacters `(`, `)`, `*`, `\\` and NUL are therefore interpreted as filter syntax instead of literal text.\n\nBoth sites now go through `LdapFilterEncoder.escapeFilterValue`, the RFC 4515 escape utility that `ActiveDirectoryGroupRealm` already uses. The filter building is extracted into two small helpers so the rendered filter can be asserted directly in unit tests, following the `expandFilterTemplate` approach already used in `LdapRealm`.\n\nThe wildcards that Zeppelin adds around the search text stay outside the escaped value, so substring matching behaves exactly as before. Only an asterisk typed by the user becomes a literal character. The configured attribute name and object class are escaped as well for defense in depth, while the raw attribute name is still used for `setReturningAttributes`.\n\nThe remaining realm branches of `getMatchedUsers` are already safe: `ActiveDirectoryGroupRealm` escapes the value in `searchForUserName`, and the `JdbcRealm` branch uses a `PreparedStatement` with a validated identifier.\n\n**2. Regular expression in the sorting comparator**\n\n`SecurityRestApi` sorted the matched users with `o1.matches(searchText + \"(.*)\")`, which compiles the search text as a regular expression. A search text of `*` therefore fails with `PatternSyntaxException: Dangling meta character \u0027*\u0027` and the endpoint responds with HTTP 500. That comparator only wants to list the users whose name starts with the search text first, which `startsWith` does without compiling anything. The replacement is a consistent comparator as well, and the alphabetical order within each group is preserved because the sort is stable.\n\n### What type of PR is it?\n\nImprovement\n\n### Todos\n\n* [x] Escape the search text at both LDAP filter building sites\n* [x] Unit tests for the rendered filters (16)\n* [x] Sort the user list without compiling the search text as a regular expression\n* [x] Endpoint test for search texts containing regex metacharacters\n\n### What is the Jira issue?\n\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6599\n\n### How should this be tested?\n\n```\n./mvnw test -pl zeppelin-server -Dtest\u003dShiroAuthenticationServiceFilterInjectionTest,SecurityRestApiTest\n```\n\n`SecurityRestApiTest.testGetUserListWithRegexMetacharacters` returns HTTP 500 without the comparator change and HTTP 200 with it. The existing LDAP realm and Shiro service tests keep passing.\n\nThe LDAP part was also verified manually against an in-memory LDAP server. With the search text `*)(cn\u003dBob`, the directory server received `(\u0026(objectclass\u003dperson)(uid\u003d*)(cn\u003dBob*))` before this change, so the `uid` condition was neutralized and an extra condition was appended. After this change the same input arrives as `(\u0026(objectclass\u003dperson)(uid\u003d*\\2a\\29\\28cn\u003dBob*))`, while a normal search text produces exactly the same filter and the same results as before.\n\nWorth noting that the entries matched by an injected filter are not disclosed in the REST response today, because `SecurityRestApi` filters the returned list once more with `containsIgnoreCase(user, searchText)`. So the LDAP part is hardening of the filter building rather than a fix for an information leak.\n\n### Screenshots (if appropriate)\n\nNot applicable.\n\n### Questions\n\n* Does the licenses files need update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5384 from kimyenac/ZEPPELIN-6599.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "07cf67087516e16c3d1c6e31716c956f6654f33e",
      "tree": "6e7eef97453b3a5e1577c4292fa1c2f7e8e33db8",
      "parents": [
        "460a2e4a6d124365a159d7733164febb1fb42801"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Thu Aug 06 16:57:06 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 16:57:06 2026 +0900"
      },
      "message": "[ZEPPELIN-6012] Fix NPE when the run-note request body carries no params\n\n### What is this PR for?\n\n`POST /api/notebook/job/{noteId}` accepts an optional request body carrying form parameters. Sending a body that supplies no parameters, either `{}` or `{\"params\":null}`, returns HTTP 500.\n\n`ParametersRequest` declares its `params` field as `final` and assigns it in the constructor, but Gson never invokes that constructor. It allocates the instance and fills the fields reflectively, so a body without a `\"params\"` entry leaves the field at its default value of `null`. `NotebookRestApi.runNoteJobs` then hands that `null` straight to `HashMap.putAll`:\n\n```java\nMap\u003cString, Object\u003e params \u003d new HashMap\u003c\u003e();\nif (!StringUtils.isEmpty(message)) {\n  ParametersRequest request \u003d GSON.fromJson(message, ParametersRequest.class);\n  params.putAll(request.getParams());\n}\n```\n\n`{}` is not an empty string, so the guard passes and the call throws:\n\n```\njava.lang.NullPointerException: Cannot invoke \"java.util.Map.size()\" because \"m\" is null\n\tat java.util.HashMap.putMapEntries(HashMap.java:495)\n\tat java.util.HashMap.putAll(HashMap.java:783)\n\tat org.apache.zeppelin.rest.NotebookRestApi.runNoteJobs(NotebookRestApi.java:850)\n```\n\nNothing catches it, so `WebApplicationExceptionMapper` turns it into a generic `Internal server error` with status 500. Running a note without form parameters is a legitimate request, and an empty body already works, so both spellings should behave the same.\n\nThis PR makes `ParametersRequest.getParams()` return an empty map instead of `null`, which covers both an absent key and an explicit null value.\n\nScope note: two other call sites parse the same request object, at `NotebookRestApi` lines 979 and 1018. Both assign the result to a local variable rather than calling `putAll`, so they do not throw, and their consumers already guard against null (`Note.runAllSync` and `NotebookService.runParagraph` each check `params !\u003d null \u0026\u0026 !params.isEmpty()`). Fixing the accessor covers all three call sites without changing their behavior.\n\n### What type of PR is it?\n\nBug Fix\n\n### Todos\n\n* [x] - Return an empty map from `ParametersRequest.getParams()` when no parameters were supplied\n* [x] - Add a regression test covering both `{}` and `{\"params\":null}`\n* [x] - Confirm the test fails without the fix and passes with it\n\n### What is the Jira issue?\n\n* [ZEPPELIN-6012](https://issues.apache.org/jira/browse/ZEPPELIN-6012)\n\n### How should this be tested?\n\nNew test `NotebookRestApiTest#testRunNoteWithoutParamsInBody` creates a note and posts both bodies to the run-note endpoint, asserting that each returns status `OK`.\n\n```bash\n./mvnw package -pl zeppelin-server --am \\\n  -Dtest\u003d\u0027NotebookRestApiTest#testRunNoteWithoutParamsInBody\u0027 -DfailIfNoTests\u003dfalse\n```\n\nReverting only the production change makes the new test fail with `Expected: HTTP response \u003c200\u003e but: got \u003c500\u003e`, and the server log shows the stack trace above. With the fix it passes.\n\nAlso verified by hand against a locally running server, posting each body to `/api/notebook/job/{noteId}`:\n\n| Request body | Before | After |\n|---|---|---|\n| `{}` | HTTP 500 | HTTP 200 |\n| `{\"params\":null}` | HTTP 500 | HTTP 200 |\n| empty body | HTTP 200 | HTTP 200 |\n| `{\"params\":{\"name\":\"zeppelin\"}}` | HTTP 200 | HTTP 200 |\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5385 from big-cir/ZEPPELIN-6012.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "460a2e4a6d124365a159d7733164febb1fb42801",
      "tree": "47c68e0afc5420e4715a011e4d40991c926ee1ae",
      "parents": [
        "8a2b306bbcc26d1cffa7737d304f72dbc1924944"
      ],
      "author": {
        "name": "huiseong29",
        "email": "tobestar29@naver.com",
        "time": "Thu Aug 06 11:11:40 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:11:40 2026 +0900"
      },
      "message": "[ZEPPELIN-6486] Rename the mislabeled \"Set up JDK 8\" CI step to JDK 11\n\n### What is this PR for?\r\nThe JDK setup step in the `flink-test-and-flink-integration-test` job of `.github/workflows/core.yml` was named \"Set up JDK 8\" while its `java-version` was already set to `11`. The name was the only thing wrong; anyone reading the workflow or the CI logs would think the job runs on JDK 8.\r\n\r\nThis renames the step to \"Set up JDK 11\", matching the correctly labeled step elsewhere in the same file. Only the display name changes — `java-version` and every other key stay exactly as they are.\r\n\r\nA grep across `.github/workflows/` confirms this was the only static JDK setup step whose name disagreed with its configured `java-version`; every other step either pins 11 with a matching name or derives the version from the build matrix.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n- [x] - Rename the step to \"Set up JDK 11\"\r\n\r\n### What is the Jira issue?\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6486\r\n\r\n### How should this be tested?\r\n`grep -rn \"Set up JDK 8\" .github/workflows/` returns no matches.\r\nThe renamed step still has `java-version: 11` and no other keys changed.\r\nThe workflow YAML still parses.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\n\nCloses #5382 from huiseong29/ZEPPELIN-6486.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "8a2b306bbcc26d1cffa7737d304f72dbc1924944",
      "tree": "1607615718c964c9d2e0183adab9cdfe646d21a1",
      "parents": [
        "2c448a3b2dd3868112235efafac58e7810a41ed0"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Thu Aug 06 11:10:23 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:10:23 2026 +0900"
      },
      "message": "[ZEPPELIN-6463] Close the package.json reader in HeliumBundleFactory with try-with-resources\n\n### What is this PR for?\n\n`HeliumBundleFactory.downloadPackage()` stages a Helium package into its bundle directory, either by copying a local directory or by unpacking an npm tarball, and then reads the `package.json` it finds there to pull out the `dependencies` and `main` entries:\n\n```java\nJsonReader reader \u003d new JsonReader(new FileReader(existingPackageJson));\nMap\u003cString, Object\u003e packageJson \u003d gson.fromJson(reader,\n        new TypeToken\u003cMap\u003cString, Object\u003e\u003e(){}.getType());\n```\n\nThe reader is never closed. There is no `close()`, no `finally` and no try-with-resources, and Gson does not close a reader handed to it. Ownership stays with the caller.\n\nThe descriptor is therefore released only once the garbage collector reclaims the `FileReader`, because `FileInputStream` registers itself for cleanup. So this is not an unbounded leak, but the release is not deterministic: the descriptor stays open for as long as the `FileReader` goes unreclaimed, which has nothing to do with the point where the parse finishes and the reader stops being useful. The same holds when parsing fails, since a malformed `package.json` makes Gson raise `JsonSyntaxException` and the method exits without closing.\n\nThis PR wraps the reader in a try-with-resources so the descriptor is released as soon as parsing finishes. Only `JsonReader` is declared as a resource, since closing it closes the `FileReader` it wraps, which avoids a redundant second close. `packageJson` is declared ahead of the block so the parsed result remains available to the rest of the method. Parsing behaviour and the resulting bundle setup are unchanged, and no signatures or access modifiers change.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] Close the `package.json` reader opened in `downloadPackage`\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6463\n\n### How should this be tested?\n\n```bash\n./mvnw package -pl zeppelin-server --am \\\n  -Dtest\u003d\u0027HeliumBundleFactoryTest,HeliumTest,HeliumLocalRegistryTest\u0027 \\\n  -DfailIfNoTests\u003dfalse\n```\n\n`Tests run: 9, Failures: 0, Errors: 0, Skipped: 0`, and `zeppelin-server` builds.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5380 from big-cir/ZEPPELIN-6463.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "2c448a3b2dd3868112235efafac58e7810a41ed0",
      "tree": "6fb90ac5c2b759c7f3c46572892c2b50b4644bce",
      "parents": [
        "a15b82c711e730e2fac08cb73bf775cc604a786d"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Thu Aug 06 11:09:19 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:09:19 2026 +0900"
      },
      "message": "[ZEPPELIN-6484] Deduplicate IdHashes and add unit tests\n\n### What is this PR for?\n\n`IdHashes` existed twice with identical behaviour — `org.apache.zeppelin.util` in `zeppelin-interpreter` and `org.apache.zeppelin.notebook.utility` in `zeppelin-server` — and neither copy had any tests.\n\nThe ticket left the scope open between \"tests only\" and \"dedupe plus tests\". This PR takes the dedupe path: `notebook.utility` held nothing but that one file, and `Note.java` was the only thing importing it, so removing it is a file deletion and an import switch. Splitting that into a second ticket would cost more than it saves.\n\n`org.apache.zeppelin.util.IdHashes` is kept as the canonical copy, matching the module dependency direction — `zeppelin-server` already depends on `zeppelin-interpreter`, not the other way round.\n\nThe new `IdHashesTest` pins what `generateId()` guarantees: the character set (digits 1-9 and A-Z without I, L and O, left out so IDs stay unambiguous when read by a person), non-emptiness, and uniqueness. `encode()` is private, so all three go through `generateId()`. The expected character set is spelled out in the test rather than read back from `IdHashes`, so a change to the dictionary shows up as a failure instead of being silently followed.\n\nNote IDs are unaffected: `IdHashes` only mints IDs and never parses them, and the two copies produced identical output, so existing notes keep reading their stored IDs as before.\n\n### What type of PR is it?\n\nImprovement\n\n### Todos\n\n* [x] - Add `IdHashesTest` against the canonical `org.apache.zeppelin.util.IdHashes`\n* [x] - Remove the `zeppelin-server` `notebook.utility` copy and switch `Note.java` to the canonical import\n* [x] - Rebuild the shaded chain and confirm `zeppelin-server` still builds\n\n### What is the Jira issue?\n\n* [ZEPPELIN-6484](https://issues.apache.org/jira/browse/ZEPPELIN-6484)\n\n### How should this be tested?\n\nNew tests:\n\n```\n./mvnw package -pl zeppelin-interpreter --am -Dtest\u003dIdHashesTest -DfailIfNoTests\u003dfalse\n```\n\n`Tests run: 3, Failures: 0, Errors: 0, Skipped: 0`\n\nDedupe, per the ticket\u0027s verification note — rebuild the shaded chain, then build `zeppelin-server`:\n\n```\n./mvnw clean package -pl zeppelin-interpreter,zeppelin-interpreter-shaded --am -DskipTests\n./mvnw package -pl zeppelin-server --am -Dtest\u003d\u0027NoteTest,InterpreterSettingTest\u0027 -DfailIfNoTests\u003dfalse\n```\n\nBoth succeed. `NoteTest` (8 tests) covers the switched import directly, since the `Note` constructor is what calls `IdHashes.generateId()`; `InterpreterSettingTest` (12 tests) covers the canonical copy\u0027s other caller. `apache-rat` reports no unapproved licenses.\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5379 from big-cir/ZEPPELIN-6484.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "a15b82c711e730e2fac08cb73bf775cc604a786d",
      "tree": "3f36fe19bde470f67af29522779a7cc6e0515a61",
      "parents": [
        "ee44170d46b6f5841bdafb4f7163cd0eda482741"
      ],
      "author": {
        "name": "namuuCY",
        "email": "156210154+namuuCY@users.noreply.github.com",
        "time": "Thu Aug 06 11:07:33 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:07:33 2026 +0900"
      },
      "message": "[ZEPPELIN-5994] Fix cron tests for ZeppelinRestApiTest\n\n### What is this PR for?\r\n\r\nThis PR fixes and re-enables the cron REST API tests that were disabled in `ZeppelinRestApiTest`.\r\n\r\nCron scheduling is disabled for security when Zeppelin runs in anonymous mode, even if the cron configuration is enabled. This PR separates the cron tests by authentication mode:\r\n\r\n- Verify that cron creation and deletion are forbidden in anonymous mode.\r\n- Add `AuthenticatedCronRestApiTest`, which starts Zeppelin with Shiro authentication enabled.\r\n- Verify the cron lifecycle for an authenticated administrator.\r\n- Verify cron folder restrictions and invalid cron expression handling.\r\n\r\n\r\n### What type of PR is it?\r\n\r\nBug Fix\r\n\r\n\r\n### Todos\r\n\r\n- [x] Verify that cron operations are rejected in anonymous mode.\r\n- [x] Add authenticated cron REST API tests.\r\n- [x] Test cron folder restrictions.\r\n- [x] Test valid and invalid cron expressions.\r\n\r\n### What is the Jira issue?\r\n\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-5994\r\n\r\n### How should this be tested?\r\n\r\nRun the focused REST API tests:\r\n\r\n```bash\r\n./mvnw -pl zeppelin-server \\\r\n  -Dtest\u003dAuthenticatedCronRestApiTest \\\r\n  test\r\n\r\n./mvnw -pl zeppelin-server \\\r\n  -Dtest\u003d\u0027ZeppelinRestApiTest#testCronDisabledInAnonymousMode\u0027 \\\r\n  test\r\n```\r\n\r\n### Questions:\r\n- Does the license files need to update? No.\r\n- Is there breaking changes for older versions? No.\r\n- Does this needs documentation? No. This PR only updates test coverage.\n\nCloses #5367 from namuuCY/master.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "ee44170d46b6f5841bdafb4f7163cd0eda482741",
      "tree": "fe76d0deebf5df7674bde965039d57b71463edbd",
      "parents": [
        "904c0898a2d5e37e2a725b99e8ae2bec982ff509"
      ],
      "author": {
        "name": "Stan",
        "email": "53285109+houhang1005@users.noreply.github.com",
        "time": "Thu Aug 06 10:04:40 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:04:40 2026 +0900"
      },
      "message": "[ZEPPELIN-6393] Fix GET job/{noteId} api, when target notebook id contains ERROR status paragraph ,it returns java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils\n\n### What is this PR for?\r\nuse this api /api/notebook/job/{noteid} ,to get every paragraph status.\r\nwhen some status is ERROR, this api will always return：\r\njava.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils\r\nand this exception come from org.apache.zeppelin.rest.message.ParagraphJobStatus\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n\r\n### Todos\r\n\r\n\r\n### What is the Jira issue?\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6393\r\n\r\n\r\n### How should this be tested?\r\n* Strongly recommended: add automated unit tests for any new or changed behavior\r\n* Outline any manual steps to test the PR here.\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\nI found some history pr and they are the same situation with this. I guess ParagraphJobStatus.java also need change from org.apache.commons.lang.StringUtils to org.apache.commons.lang3.StringUtils to solve ERROR status of paragraph.\r\n\n\nCloses #5143 from houhang1005/master.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "904c0898a2d5e37e2a725b99e8ae2bec982ff509",
      "tree": "3949d6d95a815929c33c48f30a3805091ac27301",
      "parents": [
        "9b42f2654be2fea9fdddf310686270ebc005d4d6"
      ],
      "author": {
        "name": "Lee SuJung",
        "email": "153787023+xhaktm00@users.noreply.github.com",
        "time": "Thu Aug 06 11:03:50 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:03:50 2026 +0900"
      },
      "message": "[ZEPPELIN-6489] Fix stale Shiro authentication documentation links\n\n### What is this PR for?\r\nThe Shiro authentication docs URL referenced in `conf/shiro.ini.template` and in the Kerberos/Knox authentication filter error messages no longer resolves. The stale link has three defects: it uses `http://` instead of `https://` (template only), the path is missing the `setup/` segment, and the file name is missing an underscore (`shiroauthentication.html` → `shiro_authentication.html`).\r\n\r\nThis PR updates all three pointers to the current docs address, which is published from `docs/setup/security/shiro_authentication.md`:\r\n\r\nhttps://zeppelin.apache.org/docs/latest/setup/security/shiro_authentication.html\r\n\r\nThe surrounding comment/message text is unchanged. One line in `KnoxAuthenticationFilter` is re-wrapped to keep the longer URL within the 100-character checkstyle limit.\r\n\r\n### What type of PR is it?\r\nDocumentation\r\n\r\n### Todos\r\n* [x] Update the stale URL in `conf/shiro.ini.template`, `KerberosAuthenticationFilter` and `KnoxAuthenticationFilter`\r\n\r\n### What is the Jira issue?\r\n* [ZEPPELIN-6489](https://issues.apache.org/jira/browse/ZEPPELIN-6489)\r\n\r\n### How should this be tested?\r\nNo code behavior changes — the URLs appear only in a config template comment and log messages, so no unit tests are added.\r\n\r\n* Confirm the source page exists at `docs/setup/security/shiro_authentication.md`\r\n* Confirm no stale variants remain:\r\n  ```\r\n  rg -n \"shiroauthentication|docs/latest/security/shiro|http://zeppelin.apache.org/docs/latest/security\" conf zeppelin-server\r\n  ```\r\n* Open https://zeppelin.apache.org/docs/latest/setup/security/shiro_authentication.html and confirm it loads (verified: HTTP 200)\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5361 from xhaktm00/ZEPPELIN-6489.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "9b42f2654be2fea9fdddf310686270ebc005d4d6",
      "tree": "bbeaf0dad0815d26c50af8f55a37b010e53b5a72",
      "parents": [
        "ada6cee24da67894789c7d6058af7859272283f0"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Thu Aug 06 11:02:46 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:02:46 2026 +0900"
      },
      "message": "[ZEPPELIN-6462] Close interpreter-setting.json streams with try-with-resources\n\n### What is this PR for?\n\n`InterpreterSettingManager` discovers interpreters by reading each interpreter\u0027s `interpreter-setting.json`. Two helpers do this, and neither closes the stream it opens:\n\n```java\n// registerInterpreterFromResource\ngetInterpreterListFromJson(url.openStream());\n\n// registerInterpreterFromPath\ngetInterpreterListFromJson(new FileInputStream(interpreterJsonPath.toFile()));\n```\n\nThe shared sink wraps the stream in an `InputStreamReader` and hands it to `gson.fromJson(...)`. Gson does not close a reader passed to it — the caller owns it — so the descriptor leaks on the normal path. There is no `finally` or try-with-resources either, so it also leaks when parsing throws, for example a `JsonSyntaxException` from a malformed setting file.\n\nThis is not limited to startup. After installing an interpreter through `POST /api/interpreter/install`, `InterpreterService.downloadInterpreter()` calls `refreshInterpreterTemplates()`, which re-runs the whole directory scan. Every install therefore leaks one descriptor per interpreter directory, and the leaks accumulate on a long-running server.\n\nThis PR wraps each stream in a try-with-resources at the call site that opens it. Parsing and registration behaviour is unchanged. No signatures or access modifiers change.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] Close the stream opened in `registerInterpreterFromResource`\n* [x] Close the stream opened in `registerInterpreterFromPath`\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6462\n\n### How should this be tested?\n\n```bash\n./mvnw package -pl zeppelin-server --am \\\n  -Dtest\u003d\u0027InterpreterSettingManagerTest,InterpreterFactoryTest,InterpreterSettingTest\u0027 \\\n  -DfailIfNoTests\u003dfalse\n```\n\n`Tests run: 26, Failures: 0, Errors: 0, Skipped: 0`, and `zeppelin-server` builds.\n\nNo tests accompany this change. Asserting that a stream is closed requires a seam in production code to inject a tracked stream, and an earlier revision of this PR added one — that is not worth carrying for a two-line fix, so it has been removed along with the tests that used it. The remaining change is the try-with-resources itself.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\n\nCloses #5355 from big-cir/ZEPPELIN-6462.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "ada6cee24da67894789c7d6058af7859272283f0",
      "tree": "7755045d3ebad0330117319f98b4efe23e602cca",
      "parents": [
        "e087aee5982462adbaa36c6a7c20e596b14a3b17"
      ],
      "author": {
        "name": "HyeonUk Kang",
        "email": "43662405+hyunw9@users.noreply.github.com",
        "time": "Thu Aug 06 11:00:54 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 06 11:00:54 2026 +0900"
      },
      "message": "[ZEPPELIN-6385] Refactor StringsCompleter to use method reference for Comparator\n\n### What is this PR for?\r\n\r\nThis PR refactors the anonymous Comparator implementation in StringsCompleter to use a method reference (`String::compareToIgnoreCase`).\r\nThe change simplifies the code, improves readability, and aligns the class with modern Java best practices.\r\n\r\n### What type of PR is it?\r\nRefactoring\r\n\r\n### Todos\r\n* [x] - Replace anonymous Comparator\u003cString\u003e class with method reference.\r\n\r\n### What is the Jira issue?\r\n* [[ZEPPELIN-6385]](https://issues.apache.org/jira/browse/ZEPPELIN-6385)\r\n\r\n### How should this be tested?\r\n\r\nSince the expected behavior remains unchanged, no additional tests are required.\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? - No\r\n* Is there breaking changes for older versions? - No\r\n* Does this needs documentation? - No\r\n\n\nCloses #5126 from hyunw9/ZEPPELIN-6385.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "e087aee5982462adbaa36c6a7c20e596b14a3b17",
      "tree": "33fe25a2b9b387724254ac7e6313d66f61921f07",
      "parents": [
        "404866f4171efa27abdf327a4f3d9ffaf3771909"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Wed Aug 05 23:35:34 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Aug 05 23:35:34 2026 +0900"
      },
      "message": "[ZEPPELIN-3968] Fix wrong MySQL driver class in JDBC doc screenshot\n\n### What is this PR for?\nThe \"Edit Properties\" screenshot in the JDBC interpreter documentation shows `default.driver` as `org.mysql.jdbc.Driver`, which is not a real class. Following the docs as written gives a `ClassNotFoundException`.\n\nThe correct value is `com.mysql.jdbc.Driver`, which is already what the property tables further down the same page use, so the screenshot was the only place left disagreeing with the rest of the doc.\n\nThe screenshot is patched in place rather than recaptured. It dates from the 0.7 era, and a fresh capture would no longer match the surrounding images in the same walkthrough. To keep the font rendering identical, the `c`, `o` and `m` glyphs were taken from elsewhere in the same line of text (`jdbc`, `org`, `mysql`), and the remainder of the string was shifted right by the advance width difference between \"org\" (1445/1000 em) and \"com\" (1889/1000 em), about 11px at this scale.\n\nA pixel by pixel comparison against the original confirms only the `default.driver` value changed: 3,387 pixels inside x 936-1171, y 255-278. The surrounding table, the orange highlight box and the arrow annotation are untouched.\n\n### What type of PR is it?\nDocumentation\n\n### Todos\n* [x] - Fix the driver class name in the screenshot\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-3968\n\n### How should this be tested?\nOpen the \"Files changed\" tab and use the image diff on `docs/assets/themes/zeppelin/img/docs-img/edit_properties.png`. The `default.driver` row should read `com.mysql.jdbc.Driver`, everything else unchanged.\n\nThe image is referenced from `docs/interpreter/jdbc.md`.\n\n### Screenshots (if appropriate)\nBefore: `default.driver` \u003d `org.mysql.jdbc.Driver`\nAfter: `default.driver` \u003d `com.mysql.jdbc.Driver`\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5368 from kimyenac/ZEPPELIN-3968.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "404866f4171efa27abdf327a4f3d9ffaf3771909",
      "tree": "f5f927c8fdb5feca05e0d630a8d58d70d7c9ed31",
      "parents": [
        "d3f9fa01ec453768307e2c971e5fdf1065d8e2e5"
      ],
      "author": {
        "name": "김동환",
        "email": "66408194+dev-donghwan@users.noreply.github.com",
        "time": "Tue Aug 04 00:20:09 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Aug 04 00:20:09 2026 +0900"
      },
      "message": "[ZEPPELIN-6590] Bump websocket-driver to 0.7.5 to address CVE-2026-54466\n\n### What is this PR for?\nThe lockfiles of both web UIs (`zeppelin-web-angular` and `zeppelin-web`) resolve `websocket-driver` to 0.7.4, which is affected by [CVE-2026-54466 / GHSA-xv26-6w52-cph6](https://github.com/advisories/GHSA-xv26-6w52-cph6): the draft-75/76 frame parser accumulates the length header into an unbounded integer, so a client sending an indefinite sequence of continuation bytes (`0x80` or above) causes precision loss and mis-framing of subsequent payload data. The fix is in 0.7.5 (latest release), which closes the connection as soon as the accumulated length exceeds the configured max length.\n\n`websocket-driver` is a dev-only transitive dependency (`\u003cat\u003eangular-devkit/build-angular` → `webpack-dev-server` → `sockjs` → `faye-websocket`), so shipped Zeppelin artifacts are not affected — but the vulnerable version keeps being flagged by dependency scanners.\n\nSince `faye-websocket`\u0027s constraint is `\u003e\u003d0.5.1` and `sockjs`\u0027s is `^0.7.4`, this is a lockfile-only bump: each `package-lock.json` changes only the resolved `websocket-driver` entry (version / resolved / integrity). 0.7.4 and 0.7.5 declare identical dependencies, so no other entry changes.\n\nNote: the dependabot security-update group PR #5354 covers `shell-quote` in the same directory but did not pick up `websocket-driver` (advisory published 2026-07-15, before that PR was created), presumably because it sits four levels deep in the dependency tree — hence this manual bump. The earlier bump attempt in #4798 (ZEPPELIN-6061, for a deprecation warning) was closed pending an Angular upgrade; master is on Angular 21 now, and this change does not touch `package.json` at all.\n\n### What type of PR is it?\nImprovement\n\n### Todos\n* [x] - Bump the `websocket-driver` lockfile entry to 0.7.5 in `zeppelin-web-angular/package-lock.json` and `zeppelin-web/package-lock.json`\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6590\n\n### How should this be tested?\n* `cd zeppelin-web-angular \u0026\u0026 npm ci` — installs cleanly and resolves `websocket-driver\u003cat\u003e0.7.5` (verified locally; `npm ls websocket-driver` shows a single 0.7.5 instance)\n* CI web build should pass unchanged — dev-server behavior is unaffected (0.7.5 only adds a max-length guard in frame parsing)\n\n### Screenshots (if appropriate)\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5369 from dev-donghwan/ZEPPELIN-6590.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "d3f9fa01ec453768307e2c971e5fdf1065d8e2e5",
      "tree": "37a89145fd4502fe7e28f483176a46203dda77ce",
      "parents": [
        "74fd060401a203888af1f0bc4769d95547f36de2"
      ],
      "author": {
        "name": "김동환",
        "email": "66408194+dev-donghwan@users.noreply.github.com",
        "time": "Mon Aug 03 23:28:11 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 23:28:11 2026 +0900"
      },
      "message": "[ZEPPELIN-6483][FOLLOWUP] Format HDFS modification time with Locale.ROOT\n\n### What is this PR for?\nFollow-up to #5351, addressing the non-blocking nit from the [approving review](https://github.com/apache/zeppelin/pull/5351#pullrequestreview-4820385490): `new SimpleDateFormat(pattern)` still takes its calendar and digits from the JVM default *locale*, so the same class of environment dependence survives the GMT fix — e.g. under a `th-TH` default locale the Buddhist calendar renders 2015 as `2558-08-02 20:43GMT`.\n\nThis change passes `Locale.ROOT` to the formatter in `listDate()` so the calendar and digits are stable regardless of the JVM default locale, exactly as suggested in the review.\n\nThe new test mirrors the structure of `testListDateFormatsInGmtToMatchLabel` (save/restore of the global default in `finally`), switching the default locale to `th-TH` and asserting the listing still shows `2015-08-02 20:43GMT`. Reverting only the `listDate()` change makes it fail with the Buddhist-calendar output (`2558-08-02 20:43GMT`), so it pins the regression rather than asserting current behaviour.\n\n### What type of PR is it?\nImprovement\n\n### Todos\n* [x] - Pass `Locale.ROOT` to the `SimpleDateFormat` in `listDate()`\n* [x] - Add a regression test that fails without the fix\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6483 (resolved by #5351; this is the follow-up allowed in its review)\n\n### How should this be tested?\n* `./mvnw test -pl file -Dtest\u003dHDFSFileInterpreterTest` — 8 tests green (7 existing + 1 new)\n* Verified locally that reverting only the `listDate()` change makes `testListDateFormatsWithRootLocale` fail with `2558-08-02 20:43GMT` (Buddhist calendar year) in the listing\n\n### Screenshots (if appropriate)\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5370 from dev-donghwan/ZEPPELIN-6483-followup.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "74fd060401a203888af1f0bc4769d95547f36de2",
      "tree": "79cdb23575daea77fa1b5235bbd00e6f5cdef17c",
      "parents": [
        "0fbb61137ce43db7b4fd226585b624877eeebd8e"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Mon Aug 03 23:22:44 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 23:22:44 2026 +0900"
      },
      "message": "[ZEPPELIN-3225] Add missing @Override annotations in zeppelin-server\n\n### What is this PR for?\nThe original report is about missing \u003cat\u003eOverride annotations in\nActiveDirectoryGroupRealm. Those were already added by ZEPPELIN-5130, so the\nclass is clean on current master.\n\nTo close out the issue with something useful, I scanned the whole\nzeppelin-server module for methods that implement or override a supertype\nmethod without the annotation, and found seven remaining cases:\n\n* five `toJson()` implementations of `JsonSerializable`\n  (`HeliumConf`, `NpmPackage`, `WebpackResult`, `WatcherMessage`,\n  `CredentialsInfoSaving`)\n* `shouldSkipClass` and `shouldSkipField` in `JsonExclusionStrategy`,\n  which implement Gson\u0027s `ExclusionStrategy`\n\n### What type of PR is it?\nImprovement\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-3225\n\n### How should this be tested?\nAnnotation only change with no behaviour change, so the compiler is the check.\n`./mvnw compile -pl zeppelin-server` passes, RAT reports 0 unapproved licenses,\nand Checkstyle reports no new violations in the touched files.\n\n### Questions:\n* Does the licenses files need update? No.\n* Is there breaking changes for older versions? No.\n* Does this needs documentation? No.\n\n\nCloses #5359 from kimyenac/ZEPPELIN-3225.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "0fbb61137ce43db7b4fd226585b624877eeebd8e",
      "tree": "0df1575e4af8d4973ab40ee28053c926fb95400f",
      "parents": [
        "30bb6a8367c2b75c37225f3d44a9d23bf9e63b8b"
      ],
      "author": {
        "name": "백형준",
        "email": "138356797+vividbaek@users.noreply.github.com",
        "time": "Mon Aug 03 23:21:50 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 23:21:50 2026 +0900"
      },
      "message": "[ZEPPELIN-6466] Improve RepositorySystemFactory error reporting\n\n### What is this PR for?\r\n\r\n  Replace `printStackTrace()` in `RepositorySystemFactory` with SLF4J error logging so service creation failures are handled through the configured logging framework.\r\n\r\n  Also add a meaningful message to the `RuntimeException` thrown when `locator.getService(RepositorySystem.class)` returns null.\r\n\r\n  ### What type of PR is it?\r\n\r\n  Improvement\r\n\r\n  ### Todos\r\n\r\n  * [x] Replace `printStackTrace()` with SLF4J logging\r\n  * [x] Add a descriptive exception message\r\n  * [x] Build the shaded interpreter JAR\r\n\r\n  ### What is the Jira issue?\r\n\r\n  https://issues.apache.org/jira/browse/ZEPPELIN-6466\r\n\r\n  ### How should this be tested?\r\n\r\n  The following commands were run successfully:\r\n\r\n  * `./mvnw test -pl zeppelin-interpreter --am`\r\n    * 126 tests passed\r\n  * `./mvnw clean package -pl zeppelin-interpreter,zeppelin-interpreter-shaded -DskipTests`\r\n    * Build succeeded\r\n\r\n  ### Screenshots (if appropriate)\r\n\r\n  N/A\r\n\r\n  ### Questions:\r\n\r\n  * Does the license files need to update? No\r\n  * Is there breaking changes for older versions? No\r\n  * Does this needs documentation? No\n\nCloses #5362 from vividbaek/ZEPPELIN-6466-slf4j-repository-system-factory.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "30bb6a8367c2b75c37225f3d44a9d23bf9e63b8b",
      "tree": "4f103124e752c98c06bd76b4f8b937cfcf7b6805",
      "parents": [
        "a72b8f8fb5e8c2e3cd96b595518d56d0582f3d89"
      ],
      "author": {
        "name": "백형준",
        "email": "138356797+vividbaek@users.noreply.github.com",
        "time": "Mon Aug 03 23:20:44 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 23:20:44 2026 +0900"
      },
      "message": "[ZEPPELIN-6477] Stop dumping stack trace on Groovy cancellation\n\n### What is this PR for?\r\n\r\n  Remove the `Thread.dumpStack()` call from Groovy paragraph cancellation because it writes an unnecessary stack trace directly to stderr.\r\n\r\n  The existing `t.interrupt()` call is preserved, so the paragraph cancellation behavior remains unchanged.\r\n\r\n  ### What type of PR is it?\r\n\r\n  Improvement\r\n\r\n  ### Todos\r\n\r\n  * [x] Remove the unnecessary stack dump\r\n  * [x] Preserve the thread interruption behavior\r\n  * [x] Run the Groovy module build and tests\r\n\r\n  ### What is the Jira issue?\r\n\r\n  https://issues.apache.org/jira/browse/ZEPPELIN-6477\r\n\r\n  ### How should this be tested?\r\n\r\n  ```bash\r\n  ./mvnw test -pl groovy\r\n  ```\r\n\r\n  The build completed successfully.\r\n\r\n  ### Screenshots (if appropriate)\r\n\r\n  Not applicable.\r\n\r\n  ### Questions:\r\n\r\n  - Does the license files need to update? No\r\n  - Is there breaking changes for older versions? No\r\n  - Does this needs documentation? No\n\nCloses #5364 from vividbaek/ZEPPELIN-6477-remove-groovy-cancel-stack-dump.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "a72b8f8fb5e8c2e3cd96b595518d56d0582f3d89",
      "tree": "b8bc495677d64491ec43cb8d96fb53e4b311924d",
      "parents": [
        "c2cde0f3debb0df3befcd64fcd4332c2d5857783"
      ],
      "author": {
        "name": "백형준",
        "email": "138356797+vividbaek@users.noreply.github.com",
        "time": "Mon Aug 03 23:19:09 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 23:19:09 2026 +0900"
      },
      "message": "[ZEPPELIN-6480] Stop logging terminal dashboard HTML\n\n### What is this PR for?\r\n\r\n  Remove the INFO log that writes the full rendered terminal dashboard HTML.\r\n\r\n  The dashboard HTML is already written to the paragraph output, so logging it duplicates the content, adds unnecessary log volume, and exposes terminal URL parameters in logs.\r\n\r\n  The paragraph output rendering behavior remains unchanged.\r\n\r\n  ### What type of PR is it?\r\n\r\n  Improvement\r\n\r\n  ### Todos\r\n\r\n  * [x] Remove the full dashboard HTML log\r\n  * [x] Preserve the paragraph output rendering\r\n  * [x] Run the shell module build and tests\r\n\r\n  ### What is the Jira issue?\r\n\r\n  https://issues.apache.org/jira/browse/ZEPPELIN-6480\r\n\r\n  ### How should this be tested?\r\n\r\n  ```bash\r\n  ./mvnw test -pl shell\r\n\r\n  The build completed successfully.\r\n\r\n  ### Screenshots (if appropriate)\r\n\r\n  Not applicable.\r\n\r\n  ### Questions:\r\n\r\n  - Does the license files need to update? No\r\n  - Is there breaking changes for older versions? No\r\n  - Does this needs documentation? No\n\nCloses #5365 from vividbaek/ZEPPELIN-6480-remove-terminal-dashboard-html-log.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "c2cde0f3debb0df3befcd64fcd4332c2d5857783",
      "tree": "500403b504347f993ea2834e2e9ba6071bd911c2",
      "parents": [
        "7dfc421f686ce89eb5963fb10bd7eb37dfa75717"
      ],
      "author": {
        "name": "Lee SuJung",
        "email": "153787023+xhaktm00@users.noreply.github.com",
        "time": "Mon Aug 03 23:17:42 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Aug 03 23:17:42 2026 +0900"
      },
      "message": "[ZEPPELIN-6488] Refresh stale apache/zeppelin:0.10.0 Docker tags in the quickstart docs\n\n### What is this PR for?\r\nThe three `docker run` examples in the \"Using the official docker image\" section of `docs/quickstart/install.md` pin the image to `apache/zeppelin:0.10.0`, a release from several years ago. A first-time user following the Quickstart literally ends up running an image far behind the current docs.\r\n\r\nThis PR:\r\n- updates the three examples to `apache/zeppelin:0.12.1`, the latest release tag currently available on Docker Hub\r\n- adds a one-line note next to the examples pointing to the [apache/zeppelin tags page](https://hub.docker.com/r/apache/zeppelin/tags) so readers can find the latest tag, preventing the docs from silently rotting at the next release\r\n\r\nOut of scope (open for discussion): the same stale tag also appears in `docs/interpreter/python.md`, `docs/interpreter/flink.md` (x2), `docs/interpreter/spark.md`, and `docs/interpreter/r.md`, and `docs/quickstart/docker.md` uses `FROM apache/zeppelin:0.8.0`. Would you prefer that I align those in this PR as well, or split them into a follow-up? I would be happy to do either.\r\n\r\n### What type of PR is it?\r\nDocumentation\r\n\r\n### What is the Jira issue?\r\n* [ZEPPELIN-6488](https://issues.apache.org/jira/browse/ZEPPELIN-6488)\r\n\r\n### How should this be tested?\r\nDocumentation-only change, no unit tests required.\r\n\r\n* `grep -rn \"apache/zeppelin:0.10.0\" docs/quickstart/install.md` reports no occurrences\r\n* Verified the updated command works: `docker run -p 8080:8080 --rm --name zeppelin apache/zeppelin:0.12.1` pulls the image and Zeppelin responds on the mapped port (`/api/version` returns `0.12.1`)\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No (this is a documentation change)\r\n\n\nCloses #5366 from xhaktm00/ZEPPELIN-6488.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "7dfc421f686ce89eb5963fb10bd7eb37dfa75717",
      "tree": "bbfe4a9f67e2274bb6642905d0ddfe4c1ee6c9e9",
      "parents": [
        "21b845a01d4d75a32e87dc330760eb60e5a6934b"
      ],
      "author": {
        "name": "백형준",
        "email": "138356797+vividbaek@users.noreply.github.com",
        "time": "Sun Aug 02 16:36:51 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 02 16:36:51 2026 +0900"
      },
      "message": "[ZEPPELIN-6478] Log Groovy classpath discovery failures with throwable\n\n### What is this PR for?\r\n\r\n  Pass the caught exception to SLF4J when Groovy classpath discovery fails in `GroovyInterpreter.open()`.\r\n\r\n  Previously, only `e.getMessage()` was logged, so the exception stack trace was lost. This change logs a descriptive message together with the throwable while preserving the existing non-fatal fallback behavior.\r\n\r\n  ### What type of PR is it?\r\n\r\n  Improvement\r\n\r\n  ### Todos\r\n\r\n  * [x] Pass the classpath discovery exception to SLF4J\r\n  * [x] Preserve the existing non-fatal control flow\r\n  * [x] Run the Groovy module test lifecycle\r\n\r\n  ### What is the Jira issue?\r\n\r\n  https://issues.apache.org/jira/browse/ZEPPELIN-6478\r\n\r\n  ### How should this be tested?\r\n\r\n  The following command completed successfully:\r\n\r\n  * `./mvnw test -pl groovy`\r\n    * Build succeeded\r\n\r\n  ### Screenshots (if appropriate)\r\n\r\n  N/A\r\n\r\n  ### Questions:\r\n\r\n  * Does the license files need to update? No\r\n  * Is there breaking changes for older versions? No\r\n  * Does this needs documentation? No\n\nCloses #5363 from vividbaek/ZEPPELIN-6478-log-groovy-classpath-failure.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "21b845a01d4d75a32e87dc330760eb60e5a6934b",
      "tree": "7603b896f603eaa9ddfe750f4257efc38a994651",
      "parents": [
        "d8c43cb1561bddc296f9a158eafe8477c488625f"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Sun Aug 02 11:50:28 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Aug 02 11:50:28 2026 +0900"
      },
      "message": "[ZEPPELIN-6561] Restore default SIGINT handler so python paragraph cancel works under daemon launch\n\n### What is this PR for?\r\nCancelling a running `%python` paragraph has no effect when Zeppelin is started via `zeppelin-daemon.sh`: the user code runs to completion and the result is recorded as SUCCESS while the job status becomes ABORT.\r\n\r\nThe cancel plumbing itself works. `cancel()` in `PythonInterpreter` sends SIGINT to the correct python pid, and the interpreter log shows it. The problem is signal disposition inheritance: `zeppelin-daemon.sh` starts the server with `nohup ... \u0026` from a non-interactive shell, so per POSIX the whole process chain (ZeppelinServer JVM, interpreter JVM, python) inherits SIGINT\u003dSIG_IGN, and CPython keeps SIGINT ignored instead of installing the KeyboardInterrupt handler when it starts with the signal already ignored. The SIGINT sent by `cancel()` is then a no-op. Running `signal.getsignal(signal.SIGINT)` inside an affected interpreter prints `Handlers.SIG_IGN`.\r\n\r\nThis cannot be fixed in the shell scripts, since POSIX forbids a non-interactive shell from resetting a signal that was ignored on entry. The fix restores the default SIGINT handler at the top of `zeppelin_python.py` when the inherited disposition is SIG_IGN. Starting Zeppelin in the foreground with `bin/zeppelin.sh` was never affected, which is why cancellation appears to work in some environments and not in others.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### What is the Jira issue?\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6561\r\n\r\n### How should this be tested?\r\n* Automated: `testSigintDefaultHandlerRestoredWhenInheritedIgnored` in `PythonInterpreterTest` launches the interpreter through a shell wrapper that ignores SIGINT before exec\u0027ing python, reproducing the disposition of a daemon launch, and asserts the default handler is restored inside the interpreter process. Without the fix the assertion fails with `Handlers.SIG_IGN`. Unlike the disabled `testCancelIntp`, it does not depend on timing.\r\n* Manual: start Zeppelin with `bin/zeppelin-daemon.sh start`, run a `%python` paragraph such as `for i in range(1, 50): print(i); time.sleep(0.5)`, and cancel it a few seconds in. Before the fix it runs to 49 and stores SUCCESS. After the fix it stops immediately with a KeyboardInterrupt traceback and ERROR.\r\n\r\n### Screenshots (if appropriate)\r\n#### Before\r\nhttps://github.com/user-attachments/assets/b9c6f5b4-24f6-4eb9-9019-37dab52526f0\r\n\r\n#### After\r\nhttps://github.com/user-attachments/assets/7b35d549-d97e-45cb-9d95-4ae5c543e0c0\r\n\r\n\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5346 from HwangRock/ZEPPELIN-6561.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "d8c43cb1561bddc296f9a158eafe8477c488625f",
      "tree": "3deefcc37c7b5aa2125753643f1735410e43a0e0",
      "parents": [
        "fafc11347354fdfbbfb6f341b19710a12ea0e3b0"
      ],
      "author": {
        "name": "dae won",
        "email": "99483390+big-cir@users.noreply.github.com",
        "time": "Sat Aug 01 13:16:51 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Aug 01 13:16:51 2026 +0900"
      },
      "message": "[ZEPPELIN-6579] Make notebook tree reload safe for concurrent note operations\n\n### What is this PR for?\n`NoteManager` locates a note through two separate pieces of state: `notesInfo` maps a note id to its path, and `root` holds the folder tree that the path is walked against. A lookup uses both in sequence, so the two have to agree.\n\n`reloadNotes()` replaced them one at a time:\n\n```java\npublic void reloadNotes() throws IOException {\n  this.root \u003d new Folder(\"/\", notebookRepo, noteCache, zConf);  // (1) tree becomes empty\n  this.trash \u003d this.root.getOrCreateFolder(TRASH_FOLDER);\n  init();                                                      // (2) new mapping, (3) refill tree\n}\n```\n\nNeither field is `volatile` and nothing is held while they are swapped, so a concurrent `processNote()` can observe a mapping and a tree that belong to different generations:\n\n| time | reloading thread | note request thread | state |\n|---|---|---|---|\n| t1 | installs an empty tree | | mapping: old (complete) / tree: **empty** |\n| t2 | | `notesInfo.containsKey(noteId)` passes | the id is still in the old mapping |\n| t3 | | walks the path in the tree, finds nothing | **throws** |\n| t4 | installs the new mapping | | |\n| t5 | refills the tree, one note at a time | | notes not inserted yet still fail |\n\nThe guard in `processNote()` only checks `notesInfo`, so it passes and the failure surfaces one line later in `getNoteNode()`:\n\n```\njava.io.IOException: Can not find note: /E2E_TEST_FOLDER/TestNotebook_...\n  at org.apache.zeppelin.notebook.NoteManager.getNoteNode\n  at org.apache.zeppelin.notebook.NoteManager.processNote\n  at org.apache.zeppelin.rest.NotebookRestApi.updateParagraph\n```\n\n`IOException` is not mapped to a specific status, so `WebApplicationExceptionMapper` turns it into **HTTP 500** for a note that was never removed. Everything that goes through `processNote()` is affected: reading a note, updating a paragraph, creating, deleting and moving notes, and listing the notebook.\n\nThis PR holds the tree, the trash folder and the mapping in one immutable `NoteTree` and publishes it with a single `volatile` write. `buildNoteTree()` fills the new tree locally and returns it; only then is it assigned. The tree-walking helpers (`getNoteNode`, `getFolder`, `getOrCreateFolder`, `isNotePathAvailable`) take the tree as a parameter, and callers that need both pieces of state read the reference once, so a lookup resolves the mapping and the tree against the same generation. Those helpers are `static` so that the compiler prevents them from reaching back to the field.\n\n### Scope and related issues\n**#5325** (`[ZEPPELIN-5858]`) is open against the same class and restructures `removeNote`, `moveNote` and `moveFolder` with `synchronized (this)`. It targets a different race (two mutators duplicating a note) and its monitor does not cover `reloadNotes()`, so neither change subsumes the other. Whichever merges second will need a rebase.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] - Build the new tree, trash folder and mapping in `buildNoteTree()` before publishing them\n* [x] - Hold the three in an immutable `NoteTree` published through a single `volatile` write\n* [x] - Pass the tree into the tree-walking helpers so one lookup uses one generation\n* [x] - Add a regression test that reloads while other threads read notes\n* [x] - Confirm the test fails without the fix and passes with it\n\n### What is the Jira issue?\n* [ZEPPELIN-6579](https://issues.apache.org/jira/browse/ZEPPELIN-6579)\n\n### How should this be tested?\nNew test `NoteManagerTest#testConcurrentReloadAndProcessNote`: it saves 50 notes, then runs `reloadNotes()` in a loop on one thread while four threads keep calling `processNote()` for every note, and asserts that no lookup fails or returns nothing.\n\n```bash\nexport JAVA_HOME\u003d$(/usr/libexec/java_home -v 11)\n./mvnw package -pl zeppelin-server --am -Dtest\u003dNoteManagerTest -DfailIfNoTests\u003dfalse\n```\n\nResult with the fix: `Tests run: 7, Failures: 0, Errors: 0`.\n\nReverting only the production change makes the new test fail on every reader thread with `java.io.IOException: Can not find note: /prod/note_0` thrown from `NoteManager.getNoteNode` via `NoteManager.processNote`, which is the stack from the ticket; with the fix it passes.\n\nAlso run, to cover the callers of the reload path:\n\n```bash\n./mvnw package -pl zeppelin-server --am \\\n  -Dtest\u003d\u0027NotebookTest#testReloadAllNotes+testReloadAndSetInterpreter\u0027 -DfailIfNoTests\u003dfalse\n```\n\nResult: `Tests run: 2, Failures: 0, Errors: 0`.\n\nNot verified locally: the full `NotebookTest` and `NotebookServerTest` classes, which start real remote interpreter processes and time out in my environment, and `NotebookRepoSyncTest`. Those are left to CI.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5357 from big-cir/ZEPPELIN-6579.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "fafc11347354fdfbbfb6f341b19710a12ea0e3b0",
      "tree": "46ab393b245eff45e381bb408a1f8adc9897c37d",
      "parents": [
        "f4561394eab37c3238bec8bcb30b870e748801a9"
      ],
      "author": {
        "name": "Seoyeon Lee",
        "email": "68765200+sylee6529@users.noreply.github.com",
        "time": "Fri Jul 31 23:18:21 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 31 23:18:21 2026 +0900"
      },
      "message": "[ZEPPELIN-6474] Handle NumberFormatException when parsing MongoDB interpreter numeric properties\n\n### What is this PR for?\r\n\r\n`MongoDbInterpreter.open()` parses two numeric properties, `mongo.shell.command.timeout` and `mongo.interpreter.concurrency.max`, with `Long.parseLong()` / `Integer.parseInt()` outside any `try`/`catch` — the existing try-with-resources in that method covers only the `Scanner` that loads the shell extension. When either value is empty, missing, or non-numeric, a raw `NumberFormatException` escapes `open()`.\r\n\r\nBecause `open()` is triggered lazily by the first paragraph run, this lands in the notebook paragraph as a bare stack trace that never names the property at fault. The MongoDB interpreter has several numeric properties, so the only way to tell which one failed today is to read the line number off the trace and open the source — which is not something a Zeppelin user should have to do.\r\n\r\nReproduced on JDK 11: an empty value yields `NumberFormatException: For input string: \"\"`, a non-numeric value yields `For input string: \"60s\"`, and a missing property yields a message of just `null`. One note on that last case — the issue describes it as `Cannot parse null string`, but that wording comes from newer JDKs. On the JDK 11 this project builds with, `Long.parseLong(null)` throws `NumberFormatException(\"null\")`, so the message carries even less information than the issue suggests.\r\n\r\n### What does this PR do?\r\n\r\n- Wraps each parse and re-throws the `NumberFormatException` as an `InterpreterException` that names the property and its invalid value, keeping the original exception as the cause:\r\n  ```\r\n  Invalid value for property \u0027mongo.shell.command.timeout\u0027: 60s\r\n  ```\r\n- Keeps the two parses separate so the message always points at the exact property that failed.\r\n- Adds `throws InterpreterException` to the `open()` override. The base `Interpreter.open()` already declares it, so no caller contract changes — at runtime the call goes through `LazyOpenInterpreter.open()`, which already declares it too, and the only direct caller was the test.\r\n\r\nPer the issue, the scope is deliberately narrow: no range validation, no silent fallback to default values, no unrelated changes. An invalid configuration still fails exactly as before; it just fails understandably.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6474\r\n\r\n### How should this be tested?\r\n\r\n* `./mvnw test -pl mongodb`\r\n* Four tests were added to the existing `MongoDbInterpreterTest`, covering both properties across the three failure modes named in the issue: non-numeric and missing for `mongo.shell.command.timeout`, empty and missing for `mongo.interpreter.concurrency.max`. Each asserts that an `InterpreterException` is thrown, that its message names the offending property, and that the original `NumberFormatException` is preserved as the cause. The two remaining combinations exercise the identical catch block, so they were left out rather than duplicated.\r\n* `MongoDbInterpreterTest.init()` now declares `throws InterpreterException`, since it calls `open()` on the concrete type.\r\n* To confirm the new tests are meaningful, I reverted the change to `MongoDbInterpreter` and re-ran the suite: exactly the four new tests fail with `expected: \u003cInterpreterException\u003e but was: \u003cNumberFormatException\u003e`, while the two pre-existing tests still pass. With the change applied, all six pass.\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No — a valid configuration behaves exactly as before, and an invalid one already failed. Only the exception type and its message change.\r\n* Does this needs documentation? No\r\n\n\nCloses #5356 from sylee6529/ZEPPELIN-6474-mongodb-numberformat.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "f4561394eab37c3238bec8bcb30b870e748801a9",
      "tree": "7e7b3f147e69fbed9957bbd7253c65a461e4acc4",
      "parents": [
        "c11fe272ea01d17e26218453b48a72044b980d4f"
      ],
      "author": {
        "name": "김동환",
        "email": "66408194+dev-donghwan@users.noreply.github.com",
        "time": "Fri Jul 31 23:09:29 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 31 23:09:29 2026 +0900"
      },
      "message": "[ZEPPELIN-6483] Format HDFS modification time in GMT to match the printed label\n\n### What is this PR for?\nIn the HDFS file interpreter, `listOne()` appends a hard-coded `GMT` label to the\nmodification time, but `listDate()` formats the timestamp using the JVM default\ntime zone. On any server not running in UTC, the displayed value does not match\nthe label (e.g. a file modified at `2015-08-02 20:43` GMT is shown as\n`2015-08-03 05:43GMT` on a KST server).\n\nThis PR sets the formatter\u0027s time zone to GMT in `listDate()` so the rendered\nvalue matches the existing label.\n\nWhy format in GMT (option A) rather than keep local time and fix the label (option B):\n- `modificationTime` is an absolute epoch value, so the time zone is only a\n  display choice. Formatting in GMT keeps the output identical regardless of the\n  host/JVM default zone and consistent with the label already printed.\n- Showing the interpreter JVM\u0027s local time would be ambiguous in shared HDFS /\n  remote-interpreter, multi-user setups (\"whose local time?\"), and the output\n  would vary per deployment, making it harder to reproduce and test.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] - Format the modification time in GMT in `listDate()`\n* [x] - Add a regression test that runs under a non-UTC default zone (`Asia/Seoul`) and asserts the value is rendered in GMT to match the label\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6483\n\n### How should this be tested?\n* `./mvnw test -pl file -Dtest\u003dHDFSFileInterpreterTest`\n* The new test `testListDateFormatsInGmtToMatchLabel` pins a known `modificationTime` (1438548219672 \u003d 2015-08-02 20:43 GMT) under an `Asia/Seoul` default zone and asserts the output contains `2015-08-02 20:43GMT`.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No — display-only change; on non-UTC servers the shown value changes, but it now correctly matches the label\n* Does this needs documentation? No\n\n\nCloses #5351 from dev-donghwan/ZEPPELIN-6483.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "c11fe272ea01d17e26218453b48a72044b980d4f",
      "tree": "aa76c2d83a21dbe8912c97ac70f16e3d163150d0",
      "parents": [
        "cc5c38aafb2aabefc8182ef9139bb48c333329ed"
      ],
      "author": {
        "name": "김동환",
        "email": "66408194+dev-donghwan@users.noreply.github.com",
        "time": "Fri Jul 31 00:23:32 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 31 00:23:32 2026 +0900"
      },
      "message": "[ZEPPELIN-6530] Fix operator precedence in SSL store path checks and make isWindowsPath null-safe\n\n### What is this PR for?\n`getKeyStorePath()` and `getTrustStorePath()` in `ZeppelinConfiguration` contain\na mis-parenthesized condition:\n\n```java\nif (path !\u003d null \u0026\u0026 path.startsWith(\"/\") || isWindowsPath(path)) {\n```\n\nThe condition is meant to answer a single question — \"is `path` an absolute\npath (Unix `/...` or Windows `C:\\...`)?\" — with `path !\u003d null` guarding the\nwhole check. But since `\u0026\u0026` binds tighter than `||`, it actually parses as\n`(path !\u003d null \u0026\u0026 path.startsWith(\"/\")) || isWindowsPath(path)`, leaving\n`isWindowsPath(path)` outside the null guard. `isWindowsPath` dereferences its\nargument, so a null `path` would throw an NPE.\n\nNote on reachability: with the current defaults this NPE is latent rather than\nuser-facing. `ZEPPELIN_SSL_KEYSTORE_PATH` has a non-null default (`\"keystore\"`),\nso `getKeyStorePath()` never sees a null path, and `getTrustStorePath()` falls\nback to `getKeyStorePath()` when the truststore path is unset. So this PR is a\ncorrectness/hardening fix, not a fix for a currently reproducible crash.\n\nThis PR:\n- restores the intended grouping in both methods —\n  `path !\u003d null \u0026\u0026 (path.startsWith(\"/\") || isWindowsPath(path))` — matching\n  the correctly-parenthesized pattern already used in `getAbsoluteDir()` in the\n  same class\n- makes `isWindowsPath(null)` return `false` instead of throwing, as defense\n  in depth\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] - Add the missing parentheses in `getKeyStorePath()` / `getTrustStorePath()`\n* [x] - Make `isWindowsPath` null-safe\n* [x] - Add a unit test for `isWindowsPath(null)`\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6530\n\n### How should this be tested?\n* `./mvnw test -pl zeppelin-server -Dtest\u003dZeppelinConfigurationTest`\n* The new `isWindowsPathTestNull` asserts `isWindowsPath(null)` returns `false`\n  (it threw an NPE before this change), following the existing\n  `isWindowsPathTestTrue` / `isWindowsPathTestFalse` convention.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No — behavior is unchanged for\n  all reachable inputs; only the (previously unreachable) null case changes from\n  NPE to the intended relative-path fallback\n* Does this needs documentation? No\n\n\nCloses #5353 from dev-donghwan/ZEPPELIN-6530.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "cc5c38aafb2aabefc8182ef9139bb48c333329ed",
      "tree": "a61243097c1c190694f649a59bfaf0ae1e4a161b",
      "parents": [
        "dbb58f81446f85524145234acf502574dbeaf848"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Wed Jul 29 23:29:41 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 29 23:29:41 2026 +0900"
      },
      "message": "[ZEPPELIN-6562] Fix specs that silently pass or flake because they target DOM the new UI no longer renders\n\n### What is this PR for?\r\n\r\nSeveral new UI specs target DOM that the previous UI rendered. Those selectors match no element, and the result splits two ways: some checks pass without proving anything, and some waits never resolve and time out. Both symptoms come from the same cause.\r\n\r\nThe silent passes are the heavier half. `waitForParagraphExecution` in `notebook-keyboard-page.ts` waits on `.paragraph-control .fa-spin, .running-indicator, .paragraph-status-running`. None of those classes appear in any new UI template, and `.fa-spin` is only a class definition in the vendored FontAwesome stylesheet that is never applied. The wait resolves immediately, so callers move on while the paragraph still reads `READY`. The keyboard suite uses this helper throughout.\r\n\r\nThe same selector is used as an assertion. `paragraph-functionality.spec.ts:184` is meant to confirm that a cancelled paragraph stopped running, but the locator matches nothing and `not.toBeVisible` passes whether or not execution stopped. This PR asserts that `.status` reaches `ABORT` instead. Asserting that the cancel control disappears is not enough, because that control only renders while the paragraph is `PENDING` or `RUNNING`, so it also disappears on natural completion. For the same reason the cancel has to happen after the run starts: the control is visible during `PENDING` too, so the existing code clicked it while the interpreter was still starting and exercised something other than what the test claims.\r\n\r\nThe flaky half comes from three places. The trash folder\u0027s \"Empty\" anchor collapses when the row loses hover: its bounding box is `{width:0, height:0}` unhovered and `{width:12, height:17}` hovered, so splitting reveal and click clicks empty space. A click that lands while a dialog is still running its open animation is not registered at all. And paragraphs arrive over the WebSocket, so `waitForLoadState(\u0027networkidle\u0027)` can resolve before any paragraph has rendered.\r\n\r\nStrict-mode collisions sit on top of that. `getByRole(\u0027link\u0027, { name: \u0027Job\u0027 })` matches the accessible name as a substring, so it also selects note links whose title contains \"Job\". The header and user-menu locators now pass `exact: true`, checked against the names in the templates.\r\n\r\nFallback selector chains move into the Page Object and narrow to the element that exists. The cancel button was `.cancel-para, [nz-tooltip*\u003d\"Cancel\"], [title*\u003d\"Cancel\"], button:has-text(\"Cancel\"), i[nz-icon\u003d\"pause-circle\"], .anticon-pause-circle`; only `.cancel-para` is in the new UI. The export dropdown is declared without `nzTrigger`, so ng-zorro opens it on hover rather than click, which is now encapsulated as `openExportMenu()`. The clipboard spec produced a TEXT result because `%sh` output has no `%table` marker, so the export control never rendered at all; adding the marker gives it a real TABLE result.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Confirm the removed selectors appear in no Angular template and in no React component\r\n* [x] Confirm each replacement exists and means what the test assumes\r\n* [x] Check that every changed assertion still fails when the feature is broken\r\n* [x] Run the cancel test, measure the status transitions, and set the timeout from the measurement\r\n* [x] Lint with the rules added in ZEPPELIN-6560 and confirm no new violations\r\n\r\n### What is the Jira issue?\r\nZEPPELIN-6562\r\n\r\n### How should this be tested?\r\n\r\n```bash\r\ncd zeppelin-web-angular\r\nnpm run e2e:fast -- tests/notebook/ tests/home/ tests/share/ tests/workspace/\r\n```\r\n\r\nThe clipboard spec needs a shell interpreter and skips on CI. The cancel test runs on CI against the Python interpreter; measured locally, the status goes `PENDING` to `RUNNING` and reaches `ABORT` about ten seconds after the click, which is what the assertion timeout is set from.\r\n\r\nThe dead selectors can be confirmed directly: `grep -rn \"fa-spin\\|running-indicator\\|paragraph-status-running\" zeppelin-web-angular/src` matches only the vendored FontAwesome stylesheet and no template.\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5350 from voidmatcha/fix/e2e-flaky-stabilization.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "dbb58f81446f85524145234acf502574dbeaf848",
      "tree": "0db46b36b6be23122d2cd6ad60ec1741ff48413c",
      "parents": [
        "b82f14e5e9e7da0d9182af26f41d87aea91e1a98"
      ],
      "author": {
        "name": "JangAyeon",
        "email": "67853616+JangAyeon@users.noreply.github.com",
        "time": "Tue Jul 28 23:04:19 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 28 23:04:19 2026 +0900"
      },
      "message": "[ZEPPELIN-6522] Guard HTTP interceptor unwrap against null response bodies\n\n### What is this PR for?\r\n `AppHttpInterceptor.intercept` unwraps every `HttpResponse` as `event.body.body`, assuming the Zeppelin REST envelope (`{status, message, body}`). When `event.body` is `null` — a 204 No Content, or any empty 200 response — evaluating `event.body.body` throws `TypeError: Cannot read properties of null (reading \u0027body\u0027)`, which propagates to every subscriber of that request and turns an otherwise-successful empty response into a failure.\r\n\r\nNon-enveloped JSON and `responseType: \u0027text\u0027` responses were never affected `event.body.body` is `undefined` for them, and `HttpResponse.clone()` keeps the original body when the update body is `undefined`. The defect was specific to the null-body case.\r\n\r\nThis PR guards the unwrap on `event.body` being a non-null object that actually carries a `body` field; any other response (including null-body) now passes through `event.clone()` unchanged instead of touching `.body` on it.\r\n\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n  * [x] Guard the unwrap so it only runs on a non-null object carrying a `body` field                                                                                                                                                   \r\n  * [x] Verify enveloped responses still unwrap correctly                                                                                                                                                                               \r\n  * [x] Verify null-body responses pass through without throwing\r\n\r\n### What is the Jira issue?\r\n  [ZEPPELIN-6522](https://issues.apache.org/jira/browse/ZEPPELIN-6522)\r\n\r\n### How should this be tested?\r\n  * `cd zeppelin-web-angular \u0026\u0026 npm run lint`\r\n  * Feed the four body shapes (enveloped object, non-enveloped object, text string, null) through `event.clone({ body: event.body.body })` using a real `\u003cat\u003eangular/common/http` `HttpResponse`: before the fix, only the null case throws `TypeError: Cannot read properties of null (reading \u0027body\u0027)`; after the fix, all four pass through without throwing and the enveloped case still unwraps correctly.\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5344 from JangAyeon/ZEPPELIN-6522.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "b82f14e5e9e7da0d9182af26f41d87aea91e1a98",
      "tree": "c009d5be353163979382753837cd0171b957694b",
      "parents": [
        "783e39203458e6065b8da2fbcd0ad573b9c9bb4c"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Tue Jul 28 01:09:57 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 28 01:09:57 2026 +0900"
      },
      "message": "[ZEPPELIN-6559] Drop the faked Windows user agent so Monaco keybindings match the host platform\n\n### What is this PR for?\r\n\r\n`playwright.config.js` builds the chromium project from `devices[\u0027Desktop Chrome\u0027]`, whose `userAgent` is a hardcoded `Windows NT 10.0` string regardless of the host. Monaco picks its keybinding platform by sniffing that user agent, while Playwright\u0027s key resolution (`ControlOrMeta`) and the browser\u0027s native text editing follow the real OS. On a macOS host those disagree, and two things break.\r\n\r\n1. Ctrl+P and Ctrl+N are never claimed by Monaco. The keydown reaches the document with `defaultPrevented \u003d\u003d\u003d false`, so macOS Chromium runs its native Emacs-style caret binding inside Monaco\u0027s hidden textarea. The next typed character then lands in the wrong place: pressing `Control+P` and typing `MARKER` yields `M` on its own line and `line2ARKER` below it.\r\n2. `Meta+A` select-all is a silent no-op. `pressSelectAll` resolves `ControlOrMeta+A` to `Meta+A` on macOS, but Windows-mode Monaco only binds `Ctrl+A`. No model event fires, so every select-all in the suite quietly did nothing locally.\r\n\r\nLinux CI is unaffected because its Chromium build has no native caret bindings, which is why this only ever showed up locally. Real users are not affected either: with a genuine macOS user agent Monaco runs in mac mode and calls `preventDefault`. This is a test-harness defect only.\r\n\r\nUnsetting the override is what Playwright recommends for this case (https://playwright.dev/docs/emulation#devices):\r\n\r\n\u003e Pre-configured devices assume a specific platform. For example, \"Desktop Chrome\" will provide a Windows-specific user agent string. If you would like to use the user agent specific to the platform that is running the tests, we recommend unsetting the user agent property.\r\n\r\nwebkit deliberately keeps its `Desktop Safari` mac user agent, because the page objects\u0027 `Meta+A` branch depends on it.\r\n\r\nLocal (macOS) and CI (Linux) no longer share one keybinding platform as a result. That uniformity was not worth keeping: under it, select-all on macOS produced no model event at all, so the suite ran locally without exercising what it claimed to.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Verify `navigator.userAgent` reports the host platform after the change\r\n* [x] Run the keyboard spec on macOS\r\n* [x] Run the full chromium suite on CI\r\n\r\n### What is the Jira issue?\r\nZEPPELIN-6559\r\n\r\n### How should this be tested?\r\n\r\nCI covers the regression side: the full chromium suite reports 546 passed with no failure attributable to this change.\r\n\r\nThe fix itself is only observable on a macOS host:\r\n\r\n```bash\r\ncd zeppelin-web-angular\r\nnpm run start\r\nnpx playwright test e2e/tests/notebook/keyboard/ --project\u003dchromium\r\n```\r\n\r\nBefore: 3 passed, 1 failed (`ParagraphActions.MoveCursorUp: Control+P`). Because the suite is `describe.serial`, that first failure blocks every later test in the file.\r\nAfter: 31 passed, 0 failed.\r\n\r\nTo confirm the user agent directly, read `navigator.userAgent` in any spec. It changes from the `Windows NT 10.0` string to `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...`.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5342 from voidmatcha/fix/e2e-monaco-keybinding-platform.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "783e39203458e6065b8da2fbcd0ad573b9c9bb4c",
      "tree": "94c7e1d0774dcc2b1d2dc82677b00479e3b3d7b9",
      "parents": [
        "026dafdea5ed82c2616a8ed792f57c86feddd0f3"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Tue Jul 28 00:50:25 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 28 00:50:25 2026 +0900"
      },
      "message": "[ZEPPELIN-6470] Add accessible names to icon-only buttons in the interpreter settings form\n\n### What is this PR for?\nThe interpreter settings form in the New UI has six icon-only buttons whose only child is an `\u003ci nz-icon\u003e` glyph. Without any text, `aria-label`, or `title`, assistive technology has no accessible name to announce, so a screen reader user just hears \"button\" with no indication of what it does. This fails WCAG 2.1 success criterion 4.1.2 (Name, Role, Value).\n\nThis PR adds an `aria-label` to each of them in `item.component.html`:\n* per-note process add / remove (`plus` / `minus`) in the process-mode option block\n* remove property / add property in the Properties table\n* remove dependency / add dependency in the Dependencies table\n\n`aria-label` is used rather than `nz-tooltip` because a tooltip depends on hover and does not reliably set the accessible name in the accessibility tree, so it would not satisfy 4.1.2 on its own.\n\nThe change is markup only: no logic changes and no visual changes. The buttons look and behave exactly as before. Actions that already carry text (Edit / Restart / Remove) and `\u003ca\u003e` links that already have text or a tooltip are out of scope.\n\n### What type of PR is it?\nImprovement\n\n### Todos\n* [x] - Add aria-label to every icon-only button in item.component.html\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6470\n\n### How should this be tested?\n`cd zeppelin-web-angular \u0026\u0026 npm run lint` passes (this repository has no front-end unit-test infrastructure, so verification is via lint).\n\nOptionally, open the interpreter settings page, expand an interpreter, click `Edit`, and inspect the buttons in the browser accessibility tree. Each should now report its action as the accessible name, for example \"Add property\" or \"Remove dependency\".\n\n### Screenshots (if appropriate)\nNo visual change.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5345 from kimyenac/ZEPPELIN-6470.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "026dafdea5ed82c2616a8ed792f57c86feddd0f3",
      "tree": "d7026f3f2dce63f404816d99caf84aff12809a0d",
      "parents": [
        "63609aa30df368daecfcbc075a04c76fb5c34479"
      ],
      "author": {
        "name": "JangAyeon",
        "email": "67853616+JangAyeon@users.noreply.github.com",
        "time": "Tue Jul 28 00:33:24 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 28 00:33:24 2026 +0900"
      },
      "message": "[ZEPPELIN-6447] Add Module Federation typing for the published paragr…\n\n### What is this PR for?\r\n`PublishedParagraphComponent.loadReactWidget()` read the global Module Federation container via `window.reactApp` behind a `\u003cat\u003ets-ignore` comment, so the compiler couldn\u0027t check the `container.get(...)` call that follows it.\r\n\r\n`ReactRemoteLoaderService` already declares this container\u0027s shape as `RemoteContainer` and augments `Window.reactApp` with it globally. This PR exports that existing interface and reuses it here instead of adding a second, possibly conflicting `Window.reactApp` typing.\r\n\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n  * [x] Remove the `\u003cat\u003ets-ignore` comment near `window.reactApp`\r\n  * [x] Type the container with the existing `RemoteContainer` interface (covers the `get` API used here)\r\n  * [x] Preserve the `window.reactApp not available` error when the container is missing\r\n\r\n### What is the Jira issue?\r\n [ZEPPELIN-6447](https://issues.apache.org/jira/browse/ZEPPELIN-6447)\r\n\r\n### How should this be tested?\r\n  * `cd zeppelin-web-angular \u0026\u0026 npm run lint` passes with no new errors.\r\n  * Load a published paragraph with `?react\u003dtrue` and confirm the React widget still mounts; without the remote entry script, the \"window.reactApp not available\" error still surfaces.\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5343 from JangAyeon/ZEPPELIN-6447.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "63609aa30df368daecfcbc075a04c76fb5c34479",
      "tree": "773edc167657af57911f1bb1e973f063d0923fe0",
      "parents": [
        "5ecc63ceda575fe0b9b741d0ca11f6b642ff6b12"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Mon Jul 27 23:26:06 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 23:26:06 2026 +0900"
      },
      "message": "[ZEPPELIN-6560] Lint the new UI e2e suite and document its conventions\n\n### What is this PR for?\r\n\r\nThe new UI e2e suite has never been linted. `angular.json` sets `lintFilePatterns` to `src/**/*.ts` and `src/**/*.html`, so nothing under `e2e/` is checked beyond what the TypeScript compiler catches. `zeppelin-web-angular` has no unit or component test target either: no `test` target in `angular.json`, no `npm test` script, no spec files under `src/`. The e2e suite is the app\u0027s only automated coverage, so a check in it that quietly passes goes unnoticed. Two are in the tree today. `e2e/tests/notebook/paragraph/paragraph-functionality.spec.ts:184` is meant to confirm that a cancelled paragraph stops running:\r\n\r\n```ts\r\nawait expect(page.locator(\u0027.paragraph-control .fa-spin\u0027)).not.toBeVisible({ timeout: 15000 });\r\n```\r\n\r\n`.fa-spin` is defined in the vendored FontAwesome stylesheet but applied by no Angular template, so the locator matches no element, and `not.toBeVisible` passes when a locator resolves to no DOM node. Separately, `e2e/tests/notebook/paragraph/copy-to-clipboard.spec.ts:25` attributes coverage to `PAGES.SHARE.SHARE_RESULT`, a key that does not exist: `SHARE_RESULT` lives under `PAGES.WORKSPACE`. Playwright transpiles without type checking, so the expression is `undefined` and that describe\u0027s coverage attribution is silently void. This PR fixes that one, since it is a single key. The `.fa-spin` assertion needs new page-object locators to assert anything real, so it is repaired in a follow-up change rather than here.\r\n\r\nThis PR adds `e2e/**/*.ts` to `lintFilePatterns` and applies `eslint-plugin-playwright`\u0027s recommended flat config to that path. The pre-commit hook runs `eslint --fix` through lint-staged, and `--fix` applies fixes at any severity including warnings, so an autofixable rule rewrites test code without review. `playwright/no-useless-not` rewrites `.not.toBeVisible()` into `.toBeHidden()`; both forms pass when the locator matches nothing, but the rewritten one reads as a deliberate hidden-state check, so it would make the assertion above harder to spot. That rule is off. `prefer-web-first-assertions` and `no-networkidle` are lowered from the preset\u0027s `error` to `warn`, because the suite has 13 `waitForLoadState(\u0027networkidle\u0027)` calls and 9 assertions made on extracted values, and at `error` those would block every commit until the tests are rewritten. `ng lint` exits 0 on warnings, so they record the debt without gating the build. Effective severities are 36 rules at 12 error, 21 warn, 3 off, and every error-level rule passes on the current suite.\r\n\r\nAuditing the tree against the rules the doc states turned up a few more, fixed here: an unused catch binding in `login-page.util.ts`, `eslint-disable` markers carrying the tracking key on the four ZEPPELIN-6379 skips, reasons on the `waitForTimeout` calls in `utils.ts` and `react-footer.spec.ts`, reasons on the two `eslint-disable` lines in `notebook-keyboard-page.ts`, a message on the unexplained WebKit skip in `dark-mode.spec.ts`, and the missing `PAGES` annotation in `user-menu-navigation.spec.ts`.\r\n\r\n`e2e/AGENTS.md` is updated too. It drops the `Tooling: Use e2e-skills` section, which pointed contributors at an external personal repository, along with the vendor-specific setup notes in the preamble. In their place it gains an escape-hatch contract (`// JUSTIFIED:` and `// eslint-disable-next-line ... -- \u003cwhy\u003e`) and a locator hierarchy that explains why `exact: true` matters and when a CSS selector is acceptable. Four rules that claimed more than the tree delivers were brought back in line with it: the spec path pattern, where a POM is constructed, how POM files split, and web-first assertions. The doc also records what lint does not enforce, since the plugin has no rule for always-true assertions like the one above.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n* [x] Run `npm run lint` with the e2e patterns added\r\n* [x] Check every autofixable rule for one that could change a test\u0027s meaning through the pre-commit hook\r\n* [x] Compare each override against the preset severity so the config states only real deviations\r\n* [x] Confirm every `PAGES` reference resolves\r\n\r\n### What is the Jira issue?\r\nZEPPELIN-6560\r\n\r\n### How should this be tested?\r\n\r\nThis is a lint and documentation change; no test behaviour changes.\r\n\r\n```bash\r\ncd zeppelin-web-angular\r\nnpm run lint\r\n```\r\n\r\nExpect 0 errors. The warnings are the debt described above. To see the new coverage on its own, run `npx eslint \u0027e2e/**/*.ts\u0027`; before this PR `ng lint` reported nothing for `e2e/` because the path was not in `lintFilePatterns`. Adding a violation of any error-level rule, for example `test.describe.skip(\u0027x\u0027, () \u003d\u003e {})` in a spec, should now fail the lint.\r\n\r\nThe coverage-key fix is visible in the run\u0027s annotations: `npm run e2e:fast -- tests/notebook/paragraph/copy-to-clipboard.spec.ts` attributes that describe to the `share/result` component instead of `undefined`. That spec needs a running shell interpreter, so it skips on CI.\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5348 from voidmatcha/fix/e2e-locator-conventions.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "5ecc63ceda575fe0b9b741d0ca11f6b642ff6b12",
      "tree": "91c1406b0adff662dbd6da3ff8d43d6eb515d2e9",
      "parents": [
        "4b36aa474568fddd869c6e8c3e00acfb1728ab35"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Mon Jul 27 23:20:53 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 23:20:53 2026 +0900"
      },
      "message": "[ZEPPELIN-6342] Enable the endOfLine option in Prettier and cover tsx files\n\n### What is this PR for?\n\nTwo related gaps in the `zeppelin-web-angular` Prettier setup.\n\n`.prettierrc` did not declare `endOfLine`, so the line ending the formatter enforces was never stated in the project\u0027s own config. Prettier 3 defaults to `lf` and `.editorconfig` already declares `end_of_line\u003dlf`, so the effective behavior does not change. Declaring it makes `.prettierrc` authoritative instead of dependent on those fallbacks.\n\nReact `.tsx` sources were covered by no formatter at all. The `prettier` glob in `lint` and `lint:fix` matched `{ts,js,json,css,html}` only, and `lint:react` runs ESLint alone, so nothing formatted the tsx files under `projects/zeppelin-react`. Adding `tsx` to both globs closes that gap. This PR also includes the resulting `prettier --write` output for the three files that were not formatted, `ImageRenderer.tsx`, `TableVisualization.tsx` and `PublishedParagraph.tsx`. Those changes are formatting only, with no logic change.\n\n`scss` and `less` are deliberately left out. There are no scss files, and `.less` is intentionally listed in `.prettierignore`.\n\n### What type of PR is it?\nImprovement\n\n### Todos\n* [x] - Declare `\"endOfLine\": \"lf\"` in `.prettierrc`\n* [x] - Add `tsx` to the `lint` and `lint:fix` prettier globs\n* [x] - Apply `prettier --write` to the three unformatted tsx files\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6342\n\n### How should this be tested?\n* `cd zeppelin-web-angular \u0026\u0026 npm run lint` passes, including `prettier --check` over the widened glob. The remaining `member-ordering` warnings are pre-existing and unrelated to this change.\n* `npm run lint:react` passes, and the zeppelin-react vitest suite (14 tests) still passes after the reformat.\n* `prettier --check \"**/*.tsx\"` on master flags exactly `ImageRenderer.tsx`, `TableVisualization.tsx` and `PublishedParagraph.tsx`, and passes on this branch.\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5347 from kimyenac/ZEPPELIN-6342.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "4b36aa474568fddd869c6e8c3e00acfb1728ab35",
      "tree": "6e0ef481b4c774be48a2bc3a428c76880254a7f4",
      "parents": [
        "2ad49b3d6c7b510af9a69f2e85b8ed47795c02ab"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Mon Jul 27 23:19:12 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 23:19:12 2026 +0900"
      },
      "message": "[HOTFIX] Dedupe minimatch and bump postcss in zeppelin-react\n\n### What is this PR for?\n\nThe `npm-audit` job fails on master with seven high findings, all in `devDependencies`:\n\n- `brace-expansion \u003c\u003d5.0.7`, GHSA-mh99-v99m-4gvg (DoS via unbounded expansion)\n- `postcss \u003c\u003d8.5.17`, GHSA-r28c-9q8g-f849 (path traversal in source map auto-loading)\n\n`minimatch\u003cat\u003e10.2.5` is already hoisted at the top of `zeppelin-react`\u0027s tree. The vulnerable `brace-expansion\u003cat\u003e1.1.16` comes from four *nested* copies of `minimatch\u003cat\u003e3.1.5`, under `eslint`, `\u003cat\u003eeslint/eslintrc`, `\u003cat\u003eeslint/config-array` and `eslint-plugin-react`. An `overrides` entry for `minimatch` collapses those onto the version already present, removing `minimatch\u003cat\u003e3` from the tree, and `brace-expansion` then moves 5.0.7 to 5.0.8.\n\n`postcss` moves 8.5.15 to 8.5.23 in the lockfile (`npm audit fix`, no `package.json` change; `nanoid` follows as its dependency). That is the same bump as #5341, which this supersedes.\n\nThe result is `found 0 vulnerabilities`. The gate itself is unchanged: still `--audit-level\u003dhigh` over the full dependency tree, so `devDependencies` keep their CI coverage.\n\nUpgrading the eslint side is not an alternative here. `eslint-plugin-react\u003cat\u003e7.37.5` is the latest release, declares `minimatch\u003cat\u003e^3.1.2` itself, and does not run on eslint 10 (`TypeError: contextOrFilename.getFilename is not a function` at `lib/util/version.js:31`), so no version bump removes the nested copy. Overriding `brace-expansion` alone does not work either, because 5.0.8 drops the CJS default export that `minimatch\u003cat\u003e3.1.5` calls, which gives a green audit and `TypeError: expand is not a function` on lint. Overriding both avoids that, since `minimatch\u003cat\u003e10` does not use the removed export.\n\nThe lockfile shrinks by 129 lines, dropping the four nested `minimatch` / `brace-expansion` / `balanced-match` trees and `concat-map`.\n\n### What type of PR is it?\nHot Fix\n\n### Todos\n\n### What is the Jira issue?\n\n### How should this be tested?\n\nThe `npm-audit` job on this PR. Locally, from a deleted `node_modules` in `zeppelin-web-angular/projects/zeppelin-react`:\n\n```\n$ npm ci --ignore-scripts \u0026\u0026 npm audit --audit-level\u003dhigh\nfound 0 vulnerabilities      # exit 0 (master: 7 high, exit 1)\n$ npm run lint               # exit 0\n$ npm run build              # exit 0\n$ npm test                   # 14 passed\n```\n\n### Screenshots (if appropriate)\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5352 from voidmatcha/fix/npm-audit-deps.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "2ad49b3d6c7b510af9a69f2e85b8ed47795c02ab",
      "tree": "fe8d25cff7b6f93539d561749983079d8e680d5f",
      "parents": [
        "de9f896f2f307a80b95c4b9948edbf13dcdeafff"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Mon Jul 27 22:04:54 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 22:04:54 2026 +0900"
      },
      "message": "[ZEPPELIN-6551] Fix Job Manager crash on removal broadcast for a note not in the viewer\u0027s list\n\n### What is this PR for?\n\nWhen a note is permanently deleted, the backend broadcasts a field-less `NoteJobInfo` stub (`noteName\u003dnull`, `isRemoved\u003dtrue`) to **every** Job Manager subscriber, while each viewer\u0027s initial job list is owner-filtered (`JobManagerService#getNoteJobInfoByUnixTime`).\n\nFor a note the viewer does not own, `updateJobs` fell into the `currentJobIndex \u003d\u003d\u003d -1` branch and pushed the stub into `this.jobs`. `filterJobs` then ran `job.noteName.match(noteNameReg)` and threw `TypeError: Cannot read properties of undefined (reading \u0027match\u0027)`. Because the stub persists in `this.jobs`, every subsequent `filterJobs` (each filter keystroke / job update) rethrew, so the page\u0027s filter/sort stayed broken until re-navigation.\n\nThis affects any user viewing `/jobmanager` when another user permanently deletes a note they don\u0027t own.\n\n### What does this PR do?\n\n- `updateJobs`: do not add removal stubs that aren\u0027t already in the list (`if (!updateJob.isRemoved)`). The guard is kept nested inside `if (currentJobIndex \u003d\u003d\u003d -1)` rather than merged into that condition, so a removal stub can never fall through to the `else` branch\u0027s `splice(currentJobIndex, 1)` — merging would call `splice(-1, 1)` and silently drop the last job.\n- `filterJobs`: guard `job.noteName?.match(...)` with optional chaining as defense in depth.\n\n### What type of PR is it?\n\nBug Fix\n\n### What is the Jira issue?\n\n* https://issues.apache.org/jira/browse/ZEPPELIN-6551\n\n### How should this be tested?\n\n* `cd zeppelin-web-angular \u0026\u0026 npm run lint`\n* With two users: open `/jobmanager` as user A; as user B permanently delete a note A does not own; confirm A\u0027s page keeps filtering without a console `TypeError`.\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5337 from kimyenac/ZEPPELIN-6551.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "de9f896f2f307a80b95c4b9948edbf13dcdeafff",
      "tree": "f5e80b2009866bd55189e38efd3440aa32af4ff0",
      "parents": [
        "597652e4c2e21a90511805abaf43bcc1619751b3"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Sun Jul 26 13:33:31 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 26 13:33:31 2026 +0900"
      },
      "message": "[ZEPPELIN-6550] Fix trash detection in note view so trashed notes can be permanently deleted\n\n### What is this PR for?\n\nIn the new Angular UI, opening a note that lives in the Trash showed the normal **Move to trash** action instead of **Remove permanently**, so a trashed note could not be permanently deleted from the note view — confirming the action re-nested it deeper into Trash (`/~Trash/~Trash/...`). The cron scheduler button also stayed enabled for trashed notes.\n\nRoot cause: `NoteStatusService.isTrash` used `note.name.split(\u0027/\u0027)[1]`. Since ZEPPELIN-4041 the backend sets `Note.name` to the last path segment only (no `/`), so that index is always `undefined` and `isTrash` always returned `false`. The full path lives in `note.path`, which `NoteListService.setNotes` already uses correctly.\n\nThis PR:\n- Uses `note.path` instead of `note.name` in `isTrash` (mirrors `NoteListService`).\n- Navigates back to `/` after a permanent delete, matching `moveNoteToTrash`, so the view leaves the now-deleted note instead of re-fetching it and surfacing a 404.\n\n### What type of PR is it?\nBug Fix\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6550\n\n### How should this be tested?\n* `cd zeppelin-web-angular \u0026\u0026 npm run lint`\n* Create a note, move it to Trash, open it from the Trash, and confirm the action bar offers **Remove permanently** (not re-trash) and that the cron button is disabled. Confirming the permanent delete removes the note and returns to the home view without a 404.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCloses #5336 from kimyenac/ZEPPELIN-6550.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "597652e4c2e21a90511805abaf43bcc1619751b3",
      "tree": "13d4b56a517f56abdc5b7e3291f91488e0928e25",
      "parents": [
        "a31975a05b93df960165ea292d72199c160fb323"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Sat Jul 25 11:48:51 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 11:48:51 2026 +0900"
      },
      "message": "[ZEPPELIN-6558] Drop the redundant Chromium-channel Playwright projects from CI\n\n### What is this PR for?\n\n`zeppelin-web-angular/playwright.config.js` declared five browser projects, three of them Chromium — the bundled build plus the `chrome` and `msedge` channels — so the e2e suite ran against Chromium three times per invocation. `run-playwright-e2e-tests (auth)` at ~53m is the critical path of the hour-long `frontend` workflow.\n\nZEPPELIN-6314 set the goal as \"Multi-browser support: Chromium / Firefox / WebKit\" — three engines. Nothing under `e2e/` references the `Google Chrome` or `Microsoft Edge` projects, nor the `chrome`/`msedge` channels; every browser-specific branch keys on `webkit` or `firefox` (`dark-mode.spec.ts`, `notebook-keyboard-shortcuts.spec.ts`, `editor-search-page.ts`). The two channel projects add a 3x Chromium pass without adding engine coverage.\n\nThis drops them, keeping `setup`, `chromium`, `firefox`, and `webkit`. WebKit is untouched, so ZEPPELIN-6450 is unaffected. `playwright.classic.config.js` is unaffected — it uses a single Chrome project. Follow-up from the review discussion on #5335.\n\n### What type of PR is it?\n\nImprovement\n\n### What is the Jira issue?\n\n[ZEPPELIN-6558](https://issues.apache.org/jira/browse/ZEPPELIN-6558)\n\n### How should this be tested?\n\n`frontend` workflow runs the Playwright e2e suite. Expect `run-playwright-e2e-tests (auth)` to drop from ~53m to ~27m with Chromium / Firefox / WebKit coverage retained.\n\n### Questions:\n\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5338 from HwangRock/ZEPPELIN-6558.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "a31975a05b93df960165ea292d72199c160fb323",
      "tree": "8fd437a78a8b9b030a59af842c6aa89fe59dd5ff",
      "parents": [
        "3f79619f4ea7fbccc25762db6dd56510121d49ab"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Fri Jul 24 11:28:55 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 11:28:55 2026 +0900"
      },
      "message": "[ZEPPELIN-6525] Authenticate via REST for Selenium login preconditions\n\n### What is this PR for?\n\n`test-selenium-with-spark-module-for-spark-3-5` fails on ~88% of master runs. Every failure lands in `AbstractZeppelinIT.authenticationUser`: the Bootstrap 3 login modal races its fade animation and the WebSocket `session_logout` auto-open, so the login click gets intercepted, the field is not interactable, or the modal never reaches its shown state. Across eight failing master runs the exception rotates between those three, which is why hardening any single step never held on its own. Since that helper is the shared login precondition for `AuthenticationIT`, `PersonalizeActionsIT` and `InterpreterModeActionsIT`, one racy modal destabilizes the whole job.\n\nTest-only, no production changes.\n\n- Add `authenticationUserViaRest`, which logs in with a synchronous XHR `POST /classic/api/login` issued from inside the browser\u0027s own JS context, so the browser session itself becomes authenticated. Reloading afterwards lets `app.js`\u0027s pre-bootstrap `GET /security/ticket` render the logged-in state. No modal opens, so none of its races apply. Used wherever login is only a precondition (35 call sites across the three ITs).\n- Keep `authenticationUser` as hardened by ZEPPELIN-1836, and keep `AuthenticationIT.testSimpleAuthentication` on it, so the classic login modal keeps its automated coverage.\n- Add `extractNoteIdFromCurrentUrl`, which strips any `?query`/`#fragment` after the last path segment. After a reload the SPA appends `?ref\u003d...` to note URLs, which otherwise leaks into the extracted note id and breaks the `\u003cat\u003ehref` lookups.\n- Correct `PersonalizeActionsIT.testDynamicFormAction` (see below).\n\nAn earlier approach injected a JSESSIONID obtained from a separate `java.net.http` client via `addCookie`; that session never transferred to the browser — the server logged a successful login while the browser stayed anonymous. Issuing the request inside the page authenticates the real session, which the server logs confirm (`LoginRestApi` returns the expected principal and `SecurityRestApi` then reports it for the browser).\n\nRebased onto current `master` so it sits on top of #5250.\n\n### Why `testDynamicFormAction` changes\n\nThe test asserted that a non-owner\u0027s dynamic-form edit is ignored (`Status: Before`). The server does the opposite: `NotebookService.runParagraph` applies the caller\u0027s params to that user\u0027s own paragraph copy, `Note.run` executes that copy, and `GUI.textbox` prefers the params value over the default. Nothing filters a non-owner\u0027s params.\n\nThe same wrong expectation was already corrected for `testGraphAction` in 238e03242 (ZEPPELIN-4355), which also added the owner-side check that proves isolation; the dynamic-form case was missed at the time and still has no such step. The assertion has not been revisited since 2017, and its message (`\"The output of graph mode is changed\"`) is a leftover from the graph test.\n\nIt passed until now only because a late WebSocket broadcast replaces `paragraph.settings` and reverts the typed form value before the run. The test now waits for the input to actually hold the new value, so that race fails loudly instead of passing silently.\n\nAdding the owner-side isolation step would fail on a real production bug — in personalized mode the caller\u0027s params are written to the shared master paragraph before the personalized branch is taken, and then persisted. Filed separately as ZEPPELIN-6556; not addressed here.\n\n### Scope and related issues\n\n- **ZEPPELIN-6525, login modal** — fixed, though not the way the ticket proposed. Driving the modal defensively (retrying open/fill/submit, tolerating `ElementClickInterceptedException`) was tried first and made things worse: one error became six, and ignoring the interception threw away the diagnostic the raw exception carried. Taking the modal out of the precondition path addresses the class of failure rather than one instance of it.\n- **ZEPPELIN-6525, `ParagraphActionsIT` dynamic-form sleeps** — out of scope here. `ParagraphActionsIT` reports `Tests run: 21, Failures: 0, Errors: 0` on master and on this branch, so it is not what keeps the job red. Those fixed sleeps remain a latent race and deserve a follow-up.\n- **ZEPPELIN-6526, REST session instead of per-test UI logins** — implemented, with one deviation: the proposed `addCookie` injection does not work, for the reason above, so the request is issued from inside the page instead. The `?ref\u003d` risk the ticket flagged did materialise and is handled by `extractNoteIdFromCurrentUrl`.\n- **ZEPPELIN-6556** — production isolation bug found while investigating this; filed, not fixed here.\n\n### What type of PR is it?\n\nBug Fix (test infrastructure)\n\n### What is the ticket?\n\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6525\n\n### How should this be tested?\n\nRe-run `test-selenium-with-spark-module-for-spark-3-5`. Locally:\n\n```\nZEPPELIN_SELENIUM_BROWSER\u003dchrome ./mvnw -o failsafe:integration-test failsafe:verify \\\n  -pl zeppelin-integration -Dit.test\u003dAuthenticationIT -DfailIfNoTests\u003dfalse \\\n  -Pintegration -Pusing-source-tree -Pweb-classic -Pspark-scala-2.12 -Pspark-3.5\n```\n\n`AuthenticationIT` (3/3, including the modal-based `testSimpleAuthentication`) and `PersonalizeActionsIT#testDynamicFormAction` pass locally.\n\n### Questions\n\n- Does this need documentation? No.\n\nCloses #5335 from HwangRock/ZEPPELIN-6525.\n\nSigned-off-by: Jongyoul Lee \u003cjongyoul@gmail.com\u003e"
    },
    {
      "commit": "3f79619f4ea7fbccc25762db6dd56510121d49ab",
      "tree": "333b5daa1e0d01e6e4363c4947e0b0c271b36457",
      "parents": [
        "a61908949d3e38f2a92b82c1aa2c54c72362d6fd"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Thu Jul 23 23:31:01 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 23:31:01 2026 +0900"
      },
      "message": "[ZEPPELIN-6444] Add type guard for imported note JSON to remove @ts-ignore\n\n### What is this PR for?\n`NoteImportComponent` parsed unknown JSON and used three `\u003cat\u003ets-ignore` comments to access `result.paragraphs` and `result.name`.\n\nThis PR adds a small `isImportNote()` type guard that narrows the parsed value to `ImportNote[\u0027note\u0027]`, so the paragraph check, the note-name override, and the `messageService.importNote()` call are all type-safe without suppressing the compiler.\n\n### What type of PR is it?\nImprovement\n\n### Todos\n* [x] Remove the `\u003cat\u003ets-ignore` comments in `NoteImportComponent`\n* [x] Keep the existing error behavior for invalid / non-note JSON\n* [x] Preserve the imported note name override behavior\n\n### What is the Jira issue?\n[ZEPPELIN-6444](https://issues.apache.org/jira/browse/ZEPPELIN-6444)\n\n### How should this be tested?\n* `cd zeppelin-web-angular \u0026\u0026 npm run lint` passes.\n* Import a valid note JSON (with a non-empty `paragraphs` array) — the note imports; leaving the name field empty keeps the note\u0027s original name, filling it overrides the name.\n* Import a valid-but-not-a-note JSON (no `paragraphs`) — still shows \"Invalid JSON\".\n* Import a malformed JSON payload — still shows \"JSON parse exception\".\n\n### Questions:\n* Does the license files need to be updated? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5333 from kimyenac/ZEPPELIN-6444.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "a61908949d3e38f2a92b82c1aa2c54c72362d6fd",
      "tree": "f9d74264beeb57e23cad1a5c3a772ff90a88c174",
      "parents": [
        "a454d173e52edfe413fc57341c8d5002ad6659c6"
      ],
      "author": {
        "name": "Jongyoul Lee",
        "email": "jongyoul@gmail.com",
        "time": "Thu Jul 23 10:52:53 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 10:52:53 2026 +0900"
      },
      "message": "[ZEPPELIN-1836] Make testAngularRunParagraph wait for rendered Angular output\n\n### What is this PR for?\n\n`testAngularRunParagraph` has been failing on every `frontend.yml` `test-selenium-with-spark-module-for-spark-3-5` run on master since the last green build at 6353224c on 2026-04-23. The failure is always at `ZeppelinIT.java:348`:\n\n```\norg.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.xpath: (//div[\u003cat\u003eng-controller\u003d\"ParagraphCtrl\"])[1]//div[\u003cat\u003eid\u003d\"angularRunParagraph\"] (tried for 30 second(s) with 500 milliseconds interval)\n```\n\nTracing the server log confirms the angular paragraph re-run completes successfully on the server side (paragraph FINISHED, result broadcast) and the `stalenessOf(oldAngularDiv)` check before `visibilityWait` does succeed — so the old `angularRunParagraph` div is detached as expected. The new div, however, is not detected as visible within 30s.\n\nThe race lives on the frontend side of the re-render: AngularJS\u0027 `renderAngular()` does `elem.html(generated)` and then `$compile(elem.contents())(paragraphScope)`. Between those two calls the result div can be momentarily detached or empty, which is exactly the window `visibilityWait` polls into. Once it gets a stale reference, the wait does not refetch.\n\nThis builds on the `stalenessOf` + JavaScript-click fix from [ZEPPELIN-6409](https://issues.apache.org/jira/browse/ZEPPELIN-6409) (#5209). That fix proved the *old* output was being torn down; this PR makes the wait for the *new* output equally tolerant of mid-`$compile` DOM churn.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [x] Replace single `visibilityWait` with a content-aware polling wait that re-finds the element and ignores `StaleElementReferenceException`\n* [x] Mirror the content-based pattern already used after the first run (`waitForText(\\\"Run second paragraph\\\", ...)`)\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-1836 (long-standing flaky test ticket, open since 2016)\n\n### How should this be tested?\n* CI `frontend.yml` → `test-selenium-with-spark-module-for-spark-3-5` should run `ZeppelinIT.testAngularRunParagraph` to completion without timing out at line 348.\n* Local repro (slow, requires `-Pweb-classic` and Spark 3.5):\n  ```\n  ./mvnw verify -DfailIfNoTests\u003dfalse -pl zeppelin-integration \\\n    -Pweb-classic -Pintegration -Pspark-scala-2.12 -Pspark-3.5 -Pweb-dist -Pusing-source-tree \\\n    -Dit.test\u003dZeppelinIT#testAngularRunParagraph\n  ```\n\n### Screenshots (if appropriate)\nN/A\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5250 from jongyoul/ZEPPELIN-selenium-angular-paragraph.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "a454d173e52edfe413fc57341c8d5002ad6659c6",
      "tree": "b6f4d3d66966e53619d4f7c82f319327367727dd",
      "parents": [
        "554fffe9d349bb55a23a61ac4559b28edc647268"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Wed Jul 22 10:46:37 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 22 10:46:37 2026 +0900"
      },
      "message": "[ZEPPELIN-6547] Add collaboration-mode and editor-search e2e coverage for the new UI\n\n### What is this PR for?\nAdds two e2e scenarios missing from the Angular suite and cleans up the action bar\u0027s personalized-mode toggle found along the way.\n\n- **Collaborative edit sync**: edits in one viewer propagate to a second viewer of the same note (same-principal scope).\n- **Editor find widget (per-paragraph Monaco)**: open via shortcut, match count and highlights, next/previous navigation, replace-all. The notebook-wide search/replace menu is unimplemented and tracked separately by [ZEPPELIN-6442](https://issues.apache.org/jira/browse/ZEPPELIN-6442), so its scenarios are out of scope here.\n- **Accessibility**: `aria-label` on the two icon-only personalized-mode toggle buttons (the only `src/` change).\n- **Test cleanup**: replaces the always-skipped action-bar toggle test (its gate targeted a `ng-container[ngSwitch\u003d...]` that never renders) with a real toggle round-trip test (auth mode; skipped for anonymous, where the button isn\u0027t rendered).\n\nPage objects follow `e2e/AGENTS.md` (EditorSearchPage, CollaborationPage; shared auth-skip helper in `e2e/utils.ts`).\n\n### What type of PR is it?\nImprovement\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6547\n\n### How should this be tested?\nRan the collaboration and editor-search specs 10x per mode (anonymous + auth) across all browser projects with `--retries\u003d0`, all green:\nhttps://github.com/voidmatcha/zeppelin/actions/runs/29684367065\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\nCloses #5327 from voidmatcha/fix/new-ui-personalized-toggle-e2e.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "554fffe9d349bb55a23a61ac4559b28edc647268",
      "tree": "ac7206b0c374d05ce67eb23f168c52c6bf872b7a",
      "parents": [
        "7dd659ee633466caec6e36079dc478ef36a2873d"
      ],
      "author": {
        "name": "YeonKyung Ryu",
        "email": "80758099+celinayk@users.noreply.github.com",
        "time": "Wed Jul 22 00:05:02 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 22 00:05:02 2026 +0900"
      },
      "message": "[ZEPPELIN-6502] Replace deprecated openjdk Docker image with Eclipse Temurin\n\n### What is this PR for?\r\n The root `Dockerfile` used the `openjdk:11` base image for its build stage, but that image is deprecated on Docker Hub and no longer receives updates. This PR replaces it with `eclipse-temurin:11-jdk`, the community-recommended drop-in successor, and uppercases the `AS` keyword to match modern Dockerfile (BuildKit) convention\r\n\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n* [x] Replace `FROM openjdk:11 as builder` with `FROM eclipse-temurin:11-jdk AS builder` \r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6502](https://issues.apache.org/jira/browse/ZEPPELIN-6502)\r\n\r\n### How should this be tested?\r\n* `docker build --check -f Dockerfile .` — confirms the image resolves and the Dockerfile has no lint warnings                                                                                                         \r\n* Optionally run a full `docker build -f Dockerfile .` to confirm the image still builds and produces a working Zeppelin distribution\r\n\r\n### Screenshots (if appropriate)\r\nN/A (Dockerfile change, no UI\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5331 from celinayk/ZEPPELIN-6502.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "7dd659ee633466caec6e36079dc478ef36a2873d",
      "tree": "d3d40dd30de4d120ed115d5cc877504c26d73a1c",
      "parents": [
        "52397c8cd585fd821837432ff94c2b49f4ba2fc5"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Wed Jul 22 00:03:39 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 22 00:03:39 2026 +0900"
      },
      "message": "[HOTFIX] Fix 3 high-severity npm audit vulnerabilities in zeppelin-react\n\n### What is this PR for?\n\nThe `npm-audit` CI job (`.github/workflows/frontend.yml`) is failing on `master`\nbecause `npm audit --audit-level\u003dhigh` reports 3 high-severity advisories in\nzeppelin-react\u0027s transitive dev-toolchain dependencies:\n\n| Package | Advisory | Issue |\n|---|---|---|\n| `brace-expansion` | [GHSA-3jxr-9vmj-r5cp](https://github.com/advisories/GHSA-3jxr-9vmj-r5cp) | DoS via exponential-time `{}` expansion |\n| `js-yaml` | [GHSA-52cp-r559-cp3m](https://github.com/advisories/GHSA-52cp-r559-cp3m) | Quadratic CPU on YAML merge-key chains |\n| `shell-quote` | [GHSA-395f-4hp3-45gv](https://github.com/advisories/GHSA-395f-4hp3-45gv) | Quadratic-complexity DoS in `parse()` |\n\nAll three are non-breaking, in-range fixes applied via `npm audit fix`\n(lockfile-only; `package.json` is untouched). Resolved versions:\n`brace-expansion` 1.1.16 / 5.0.7, `js-yaml` 4.3.0, `shell-quote` 1.10.0.\n\n### What type of PR is it?\n\nHotfix (CI)\n\n### What is the Jira issue?\n\nN/A — CI hotfix, no functional change.\n\n### How should this be tested?\n\nVerified locally under CI-matching Node 22.21.1 (`.nvmrc`) / npm 10.9.4:\n\n- `cd zeppelin-web-angular/projects/zeppelin-react`\n- `npm ci --ignore-scripts \u0026\u0026 npm audit --audit-level\u003dhigh` → `found 0 vulnerabilities` (exit 0 — the exact npm-audit CI step)\n- `npm test` → 13 passed\n- `npm run lint` → no issues\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n- Does the licenses files need to update? No\n- Is there breaking changes for older versions? No\n- Does this needs documentation? No\n\n\nCloses #5334 from voidmatcha/hotfix/react-npm-audit.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "52397c8cd585fd821837432ff94c2b49f4ba2fc5",
      "tree": "db235f442c13770548ac8130ed76ba5a6d417e18",
      "parents": [
        "fb7f9dc86f2966395610cf8fa7942f6a56abf274"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Wed Jul 22 00:02:43 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 22 00:02:43 2026 +0900"
      },
      "message": "[ZEPPELIN-6443] Avoid misleading elapsed-time footer when a running paragraph has no dateStarted\n\n### What is this PR for?\n\nThe Angular paragraph footer fell back to `new Date()` when `dateStarted` was undefined for a running paragraph, which rendered a misleading `Started less than a minute ago.` message — implying the run had just started when the real start time was simply unknown (a race where the paragraph is `RUNNING` before `dateStarted` is populated).\n\nThis PR shows a neutral `Running…` label instead when the start time is unknown, and keeps the existing `Started X ago.` output when `dateStarted` is present. The same bug/fix applies to the React `ParagraphFooter` twin, and a unit test is added there for the missing-`dateStarted` case (the Angular project has no unit-test setup).\n\nThe pre-existing `TODO(hsuanxyz) dateStarted undefined after start` is resolved.\n\n### What type of PR is it?\n\nBug Fix\n\n### What is the Jira issue?\n\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6443\n\n### How should this be tested?\n\n- `cd zeppelin-web-angular \u0026\u0026 npm run lint`\n- React unit tests: `cd zeppelin-web-angular/projects/zeppelin-react \u0026\u0026 npm test` (covers the `Running…` / missing-`dateStarted` case)\n- Manually: run a paragraph and confirm the running (elapsed-time) and finished (execution-time) footers still render correctly.\n\n### Screenshots (if appropriate)\n\nN/A\n\n### Questions:\n\n- Does the licenses files need to update? No\n- Is there breaking changes for older versions? No\n- Does this needs documentation? No\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCloses #5330 from kimyenac/ZEPPELIN-6443.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    },
    {
      "commit": "fb7f9dc86f2966395610cf8fa7942f6a56abf274",
      "tree": "e9c8f1ee9d7f225580203938d065dae0d09729d5",
      "parents": [
        "9521f7cb8a49656d844882257f318358588b8320"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Tue Jul 21 22:48:54 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 21 22:48:54 2026 +0900"
      },
      "message": "[ZEPPELIN-6540] Make ConnectionManager.userSocketMap thread-safe\n\n### What is this PR for?\n`ConnectionManager.userSocketMap` (`user -\u003e Queue\u003cNotebookSocket\u003e`) is a plain `HashMap`, but every access to it is unsynchronized: `addUserConnection`/`removeUserConnection` (writes) and `multicastToUser`/`unicastParagraph`/`forAllUsers`/`broadcastNoteListExcept` (reads and `keySet()` iteration). The sibling field `noteSocketMap` is guarded by `synchronized (noteSocketMap)` at every access — only `userSocketMap` was left unprotected.\n\nThese paths run on different Jetty WebSocket threads (login `onMessage`, disconnect `onClose`, note-list broadcast `broadcastNoteListUpdate`). Under concurrent connect/disconnect — e.g. a burst of client reconnects after a server restart — this leads to:\n- `ConcurrentModificationException` while iterating `keySet()`, aborting the note-list broadcast so some users stop receiving updates\n- possible CPU spin / lost entries during `HashMap` resize\n- `NullPointerException` from the `containsKey` + `get` TOCTOU in `multicastToUser`/`unicastParagraph`\n\nThe map value is already a `ConcurrentLinkedQueue`, so only the map itself was unprotected.\n\nFix: switch `userSocketMap` to `ConcurrentHashMap` and make the compound operations atomic:\n- `addUserConnection`: `compute(...)` so the queue create-or-reuse and the `add` happen in one atomic map operation (closing the add-after-remove window that a bare `computeIfAbsent(...).add(...)` would leave open)\n- `removeUserConnection`: `computeIfPresent(...)`, removing the key when the queue becomes empty\n- `multicastToUser` / `unicastParagraph`: a single `get()` + null check, removing the TOCTOU/NPE\n- `forAllUsers` / `broadcastNoteListExcept`: unchanged — `keySet()` iteration is safe under `ConcurrentHashMap`\u0027s weakly-consistent iterator\n\n`noteSocketMap` intentionally keeps `synchronized`: it needs multi-entry atomic operations (`removeConnectionFromAllNote`, `checkCollaborativeStatus`) that a per-key `ConcurrentHashMap` guarantee does not cover, so a single-strategy migration would not be correct there.\n\n### What type of PR is it?\nBug Fix\n\n### Todos\n* [ ] - none\n\n### What is the Jira issue?\n* https://issues.apache.org/jira/browse/ZEPPELIN-6540\n\n### How should this be tested?\nAdded two unit tests in `ConnectionManagerTest`:\n- `userSocketMapConcurrentAccessTest`: 8 writer threads add/remove connections while 2 reader threads iterate via `forAllUsers`. On the old `HashMap` this reproduces `ConcurrentModificationException` / `NullPointerException`; with the fix it passes with no thrown exception.\n- `userSocketMapConcurrentAddPreservesAllConnectionsTest`: 16 threads concurrently add unique sockets for the same user, then assert every socket is present and the final queue size matches — validates the atomic publish `compute()` guarantees.\n\nRan the full `ConnectionManagerTest` 5× consecutively — stable, no intermittent failures.\n\nNote on the add-after-remove window: it is extremely narrow and did not reproduce as a deterministic failing test even under heavy contention (16 churn threads, 16×5000 iterations). The `compute()` fix closes it by construction (atomic per-key create-and-add under `ConcurrentHashMap`); the correctness rests on that plus the concurrent-add invariant test rather than a RED→GREEN of the exact interleaving.\n\n### Screenshots (if appropriate)\n\n### Questions:\n* Does the license files need to update? No.\n* Is there breaking changes for older versions? No — public method signatures are unchanged.\n* Does this needs documentation? No.\n\n\nCloses #5306 from HwangRock/ZEPPELIN-6540.\n\nSigned-off-by: ParkGyeongTae \u003cgyeongtae@apache.org\u003e"
    },
    {
      "commit": "9521f7cb8a49656d844882257f318358588b8320",
      "tree": "b12af236e1ad999e8c8a82bad0625fc1354a5ac0",
      "parents": [
        "0bd5b0329ad4dd50ed006a2fac904e67e072dd04"
      ],
      "author": {
        "name": "김동환",
        "email": "66408194+dev-donghwan@users.noreply.github.com",
        "time": "Tue Jul 21 00:21:15 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 21 00:21:15 2026 +0900"
      },
      "message": "[ZEPPELIN-6479] Harden Hive version parsing against missing-dot and qualifier-suffix versions\n\n### What is this PR for?\n`HiveUtils.isProgressBarSupported(String)` decides whether to show the Hive query progress bar by parsing the version returned by `HiveVersionInfo.getVersion()`. The previous implementation split the version on `.` and parsed the first two tokens with `Integer.parseInt` with no validation, so it threw for two version shapes that real Hive builds can produce:\n\n- **Missing dot** (e.g. `\"2\"`): the split yields a single-element array, so reading `tokens[1]` throws `ArrayIndexOutOfBoundsException`.\n- **Qualifier suffix** (e.g. `\"3-cdh\"`, `\"2.3-dev\"`): a numeric segment carries a trailing qualifier, so `Integer.parseInt` throws `NumberFormatException`.\n\nEither exception propagates into `startHiveMonitorThread()` and can break Hive job monitoring setup.\n\nThis PR makes the parser return a boolean for any input without throwing:\n- strips any qualifier after the numeric version (`\"3-cdh\"` -\u003e `\"3\"`, `\"2.3-dev\"` -\u003e `\"2.3\"`),\n- treats a missing minor segment as absent (`\"3\"` -\u003e major 3 \u003d supported, `\"2\"` -\u003e major 2 with no minor \u003d not supported),\n- returns `false` for null / blank / otherwise unparsable versions.\n\nThe support rule is unchanged (progress bar is supported from Hive 2.3, HIVE-16045); it is only made robust and expressed as explicit tiers: major \u003e\u003d 3 always supported, major \u003c\u003d 1 unsupported, major \u003d\u003d 2 depends on minor \u003e\u003d 3.\n\n### What type of PR is it?\nBug Fix\n\n### What is the Jira issue?\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6479\n\n### How should this be tested?\n`./mvnw test -pl jdbc -Dtest\u003dHiveUtilsTest`\n\nThe new `testIsProgressBarSupported` calls `HiveUtils.isProgressBarSupported` directly — the method is made package-private to match its sibling helpers in the same class (`extractMRJobURL`, `extractTezAppId`), which are already package-private and unit-tested the same way (no reflection). Testing through the only caller (`startHiveMonitorThread`) is not practical because the version is obtained internally from `HiveVersionInfo.getVersion()` and the method needs a live `HiveStatement`, so the edge-case versions cannot be injected. Cases cover the 2.3 boundary, both failure modes, null/blank input, and recent Maven Central releases (Hive 4.2.0 and 4.0.0-beta-1).\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this needs documentation? No\n\n\nCloses #5328 from dev-donghwan/ZEPPELIN-6479.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "0bd5b0329ad4dd50ed006a2fac904e67e072dd04",
      "tree": "6e4052b0565df74db323fae2a0ef5dfaf597030b",
      "parents": [
        "12399c7acfbf81b86dbbb122c9ac415fdd380e83"
      ],
      "author": {
        "name": "YeonKyung Ryu",
        "email": "80758099+celinayk@users.noreply.github.com",
        "time": "Tue Jul 21 00:18:21 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 21 00:18:21 2026 +0900"
      },
      "message": "[ZEPPELIN-6322] Filter download messages in ProcessData error stream\n\n### What is this PR for?\r\nThis PR improves error stream output filtering in the `ProcessData` class to exclude download-related messages. Currently, Maven/npm download progress information clutters the error stream during integration tests, making it difficult to identify actual errors.\r\nThis change filters out download messages (e.g., \"Downloading:\", \"Progress: 45%\", \"1024/2048 KB\") while preserving real error messages.\r\n\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n\r\n  ### Todos\r\n  * [x] - Add DOWNLOAD_PATTERNS array with 6 regex patterns\r\n  * [x] - Implement isDownloadMessage() method\r\n  * [x] - Apply filtering logic in buildOutputAndErrorStreamData()\r\n \r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6322](https://issues.apache.org/jira/browse/ZEPPELIN-6322)\r\n\r\n### How should this be tested?\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5104 from celinayk/ZEPPELIN-6322.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "12399c7acfbf81b86dbbb122c9ac415fdd380e83",
      "tree": "c19dfb20ce19f99693d001a043017c942c7215cc",
      "parents": [
        "aad361148cdab6348c47f187909f88f30a83dd41"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Mon Jul 20 23:28:20 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 23:28:20 2026 +0900"
      },
      "message": "[ZEPPELIN-6464] Throw IllegalArgumentException for an unsupported Scala version in SparkInterpreterLauncher\n\n### What is this PR for?\r\nThis PR updates `SparkInterpreterLauncher` to throw `IllegalArgumentException` when the Scala version parsed from `spark-submit --version` is outside the supported range.\r\n\r\nUnsupported Scala versions are invalid input values for this validation path, so `IllegalArgumentException` better describes the failure than a generic `Exception`.\r\n\r\nThe exception message is intentionally unchanged, and the `detectSparkScalaVersion(...)` method signature still declares `throws Exception` because the method can still raise checked exceptions from process execution, stream reading, and fallback Scala version detection.\r\n\r\nThis is behavior-preserving for callers: the existing caller catches `Exception` and wraps it in an `IOException`, so the surfaced behavior and public API remain unchanged.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6464\r\n\r\n### How should this be tested?\r\n* Build and run the module tests:\r\n```  \r\n./mvnw test -pl zeppelin-server --am\r\n```\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5326 from miinhho/refactor/throw-illegal-exception-in-unsupported-scala.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "aad361148cdab6348c47f187909f88f30a83dd41",
      "tree": "b622b01a2bc9c7cf8120d1f42bfa1c766d563cb8",
      "parents": [
        "226b0a6b3b26a158b460af79d44176d318c80011"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Mon Jul 20 23:27:32 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 23:27:32 2026 +0900"
      },
      "message": "[ZEPPELIN-6497] Refresh stale Cassandra interpreter embedded help links\n\n### What is this PR for?\r\nThe Cassandra interpreter help menu was linked to old Zeppelin `0.6.0-SNAPSHOT` documentation pages for dynamic forms and interpreter binding mode. Those links used outdated paths and HTTP URLs, which could send users to stale documentation.\r\n\r\nThis PR updates those embedded help links to the current Zeppelin documentation URLs under `https://zeppelin.apache.org/docs/latest/usage/...`.\r\n\r\n### What type of PR is it?\r\nDocumentation\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6497\r\n\r\n### How should this be tested?\r\n* Search for stale links:\r\n```\r\nrg -n \"0\\.6\\.0-SNAPSHOT|manual/dynamicform|manual/interpreters\" cassandra/src/main/resources/scalate/helpMenu.ssp\r\n```\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5324 from miinhho/docs/refresh-stale-cassandra-help-link.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "226b0a6b3b26a158b460af79d44176d318c80011",
      "tree": "b7cff011026c2e89c48b1fd127f8ae7da0aed11b",
      "parents": [
        "8c199a29cb7f03c164509ea2ba04f8c336e68cfb"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Mon Jul 20 23:26:40 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 23:26:40 2026 +0900"
      },
      "message": "[ZEPPELIN-6441] Replace outdated type assertions with satisfies\n\n### What is this PR for?\nThe Angular UI now uses TypeScript ~5.9.3, so the pre-4.9 workaround TODOs that asked to replace broad type assertions with `satisfies` are obsolete. This replaces those outdated assertions with `satisfies`, which improves compile-time checking without changing runtime behavior.\n\n- `app.module.ts`: `as JoinedEditorOptions` → `satisfies JoinedEditorOptions`, so unsupported editor options are caught at compile time.\n- `create-repository-modal.component.ts`: `as Record\u003c...\u003e` → `satisfies Record\u003c...\u003e`, so every form control key is validated against `CreateInterpreterRepositoryForm`.\n- `notebook-paragraph-keyboard-event-handler.ts`: `as const` → `as const satisfies ...` for both the action→handler map and the Monaco-handled action list. `as const` is intentionally kept so the downstream `typeof`-based literal indexing still narrows correctly, while `satisfies` now validates keys/values (e.g. invalid handler names are rejected).\n\nAll three changes are compile-time-only annotations; runtime behavior is unchanged.\n\n### What type of PR is it?\nImprovement\n\n### What is the Jira issue?\n[ZEPPELIN-6441](https://issues.apache.org/jira/browse/ZEPPELIN-6441)\n\n### How should this be tested?\n- `cd zeppelin-web-angular \u0026\u0026 npm run lint` passes (0 errors).\n- Verified the `satisfies` checks are active: injecting an unsupported editor option is caught as TS2353, and an invalid handler name is caught as TS2418.\n\n### Questions:\n* Does the license files need to update? No\n* Is there breaking changes for older versions? No\n* Does this need documentation? No\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCloses #5323 from kimyenac/ZEPPELIN-6441.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "8c199a29cb7f03c164509ea2ba04f8c336e68cfb",
      "tree": "a94b3fd180e672a6ca11db94d3cda714852f5b86",
      "parents": [
        "b572a07156324c6ae9c08da6ac82c9215877741f"
      ],
      "author": {
        "name": "JangAyeon",
        "email": "67853616+JangAyeon@users.noreply.github.com",
        "time": "Mon Jul 20 23:25:37 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 23:25:37 2026 +0900"
      },
      "message": "[ZEPPELIN-6532] Complete destroy$ in paragraph ngOnDestroy to stop leaking subscriptions\n\n### What is this PR for?\r\nDestroying a notebook paragraph did not tear down its own long-lived subscriptions or the shortcut key listeners it registered. ngOnDestroy() only called super.ngOnDestroy(), which (via MessageListenersManager) unsubscribes\r\n  the \u003cat\u003eMessageListener subscriptions but never touches destroy$. Subscriptions gated on takeUntil(this.destroy$) - keyBinderService.keyEvent(), angularContextManager.runParagraphAction(), and .contextChanged() - are on singleton services, so a destroyed paragraph instance stayed reachable and kept receiving callbacks after being removed from the DOM. The shortcut keydown listeners registered by KeyBinder via shortcutService.bindShortcut() were also never released.\r\n\r\nThis PR emits and completes destroy$ in ngOnDestroy, after super.ngOnDestroy(), matching the pattern already used in result.component.ts and dynamic-forms.component.ts.\r\n\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n- [x] Emit and complete destroy$ in paragraph ngOnDestroy\r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6532](https://issues.apache.org/jira/browse/ZEPPELIN-6532)\r\n\r\n\r\n### How should this be tested?\r\n* `cd zeppelin-web-angular \u0026\u0026 npm run lint`\r\n* At runtime, subscribe to a paragraph component\u0027s destroy$, then remove it (or navigate away): before the fix destroy$ never completes even though the paragraph is removed from the DOM; after the fix it completes on destroy, and the keyEvent/runParagraphAction/contextChanged subscriptions stop firing along with the shortcut keydown listeners.                                         \r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5322 from JangAyeon/ZEPPELIN-6532.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "b572a07156324c6ae9c08da6ac82c9215877741f",
      "tree": "611a2e2240395a94df728a091742cbcc97eaa662",
      "parents": [
        "09ba0e0139a58b75cbace12129182b8c7d2ccf90"
      ],
      "author": {
        "name": "HyeonUk Kang",
        "email": "43662405+hyunw9@users.noreply.github.com",
        "time": "Mon Jul 20 23:03:00 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 23:03:00 2026 +0900"
      },
      "message": "[ZEPPELIN-5876] Implement DockerInterpreterProcess.isAlive() using container state\n\n### What is this PR for?\r\n\r\nThe Docker launcher\u0027s isAlive() isn\u0027t really implemented. It just calls isRunning(), which only checks whether the interpreter\u0027s Thrift port accepts a connection (checkIfRemoteEndpointAccessible). That tells you the port is open, not that the process behind it is alive. A container can be OOMKilled or already gone and still look alive if the port happens to answer for a moment. It also doesn\u0027t match the InterpreterClient contract, which says isAlive should reflect process status and stay separate from running. The method still had //TODO(ZEPPELIN-5876): Implement it more accurately sitting on it.\r\n\r\nWhile I was there I filled in getErrorMessage(), which always returned null. When the container isn\u0027t running it now says why: OOMKilled, or a non-zero exit code. That logic lives in a small describeContainerFailure() helper to keep getErrorMessage() short.\r\n\r\nOne change is test-only: the docker field is now \u0027VisibleForTesting\u0027, so tests can inject a mock DockerClient and skip needing a real daemon.\r\n\r\n### What type of PR is it?\r\nFeature\r\n\r\n### Todos\r\n- [x] Implement isAlive() from the container\u0027s actual state (running/paused)\r\n- [x] Implement getErrorMessage() (OOMKilled / exit code)\r\n- [x] Unit tests with a mocked DockerClient\r\n\r\n### What is the Jira issue?\r\n[[ZEPPELIN-5876]](https://issues.apache.org/jira/browse/ZEPPELIN-5876)\r\n\r\n### How should this be tested?\r\nAutomated unit tests in DockerInterpreterProcessTest :\r\n- isAlive_trueWhenContainerRunning - running \u003d\u003d true → alive\r\n- isAlive_falseWhenContainerExitedOrOomKilled — running \u003d\u003d false → not alive\r\n- getErrorMessage_reportsOomKilled - oomKilled \u003d\u003d true → message contains the reason\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update? - no\r\n* Is there breaking changes for older versions? - no\r\n* Does this needs documentation? - no \r\n\n\nCloses #5316 from hyunw9/ZEPPELIN-5876.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "09ba0e0139a58b75cbace12129182b8c7d2ccf90",
      "tree": "f6b086479e082eaef299ea74e20625c95fd0c6e0",
      "parents": [
        "1355de15de9247a55e3bcf6f76a11a42d21bad8d"
      ],
      "author": {
        "name": "JangAyeon",
        "email": "67853616+JangAyeon@users.noreply.github.com",
        "time": "Mon Jul 20 23:01:32 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 23:01:32 2026 +0900"
      },
      "message": "[ZEPPELIN-6535] Match table column filter terms literally instead of as regex\n\n### What is this PR for?\r\nTyping a regular-expression metacharacter (for example `[`, `(`, `*`) into a Table visualization\u0027s per-column      \r\nsearch box threw an uncaught SyntaxError and silently broke the column filter, because the term was compiled as a  \r\nregular expression. In `filterRows()`, each column\u0027s filter predicate called `String(row[key]).search(value.term)`,\r\nand `String.prototype.search()` coerces its argument to a RegExp, so the raw user-typed term became a pattern;     \r\nbenign metacharacters such as `.` or `*` also silently changed the match semantics instead of throwing an error.   \r\n                                                                                                                   \r\nThis PR replaces `.search()` with `String.prototype.includes()`, so the term is always matched as a literal        \r\nsubstring instead of being compiled as a regex. The term is also trimmed before matching, so leading/trailing      \r\nwhitespace typed into the search box doesn\u0027t affect the result.     \r\n\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n  - [x] Match table column filter terms literally instead of compiling them as a RegExp                              \r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6535](https://issues.apache.org/jira/browse/ZEPPELIN-6535)\r\n\r\n### How should this be tested?\r\n  - `cd zeppelin-web-angular \u0026\u0026 npm run lint`                                                                        \r\n  - Produce a Table result (e.g. run `print(\"%table Name\\tValue\\nAlice\\t10\\nBob\\t20\")` in a `%python` paragraph),    \r\n  open a column\u0027s filter dropdown (▼ icon) and type `[` into the search box: before the fix, filtering breaks with an\r\n  `Invalid regular expression` error in the console and stops updating; after the fix it filters literally with no   \r\n  error.                                                                                                             \r\n  - Type an ordinary substring (e.g. `Ali`): matching behavior is unchanged from before the fix.        \r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5320 from JangAyeon/ZEPPELIN-6535.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "1355de15de9247a55e3bcf6f76a11a42d21bad8d",
      "tree": "2da1b22a5d50563dbf2bb7e3ec70873cbf088c97",
      "parents": [
        "03c9d16c10ef76d36c4749ad5d246961ca766c80"
      ],
      "author": {
        "name": "gyowoo1113",
        "email": "58352333+gyowoo1113@users.noreply.github.com",
        "time": "Sun Jul 19 17:10:01 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 17:10:01 2026 +0900"
      },
      "message": "[ZEPPELIN-6435] Remove frontend build dependency from IndexHtmlServletTest\n\n### What is this PR for?\r\n`IndexHtmlServletTest` included a disabled Angular HTML addon test because it depended on the generated file at `zeppelin-web-angular/dist/zeppelin/index.html`. That artifact is not built during normal `zeppelin-server` tests, so the test could not run independently.\r\n\r\nThis PR replaces the frontend build dependency with a temporary, test-owned `index.html` file and re-enables `testZeppelinWebAngularHtmlAddon`.\r\n\r\nThe `zeppelin-web` index and the Angular-style index exercise different branches in `IndexHtmlServlet`. The `zeppelin-web` index does not contain explicit `\u003c/head\u003e` and `\u003c/body\u003e` closing tags, so the servlet falls back to inserting the head addon before `\u003cbody\u003e` and the body addon before `\u003c/html\u003e`. The Angular-style index contains both closing tags, so the re-enabled test verifies that the configured head and body addons are inserted immediately before `\u003c/head\u003e` and `\u003c/body\u003e`.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n- [x] Remove the dependency on `zeppelin-web-angular/dist/zeppelin/index.html`\r\n- [x] Create a temporary, test-owned Angular-style `index.html`\r\n- [x] Re-enable `testZeppelinWebAngularHtmlAddon`\r\n- [x] Verify addon insertion before `\u003c/head\u003e` and `\u003c/body\u003e`\r\n\r\n### What is the Jira issue?\r\n[[ZEPPELIN-6435]](https://issues.apache.org/jira/browse/ZEPPELIN-6435)\r\n\r\n### How should this be tested?\r\n`./mvnw test -pl zeppelin-server -Dtest\u003dIndexHtmlServletTest` passes successfully.\r\n\r\n### Screenshots (if appropriate)\r\nN/A\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5314 from gyowoo1113/ZEPPELIN-6435-index-html-servlet-test-frontend-independence.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "03c9d16c10ef76d36c4749ad5d246961ca766c80",
      "tree": "7632b69b7b361635863a718387094b56f8e01301",
      "parents": [
        "63e32d74c960d138531f79487fc4bb88b56606a2"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Sun Jul 19 15:40:36 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 15:40:36 2026 +0900"
      },
      "message": "[ZEPPELIN-6498] Fix broken interpreter binding mode link in interpreter overview docs\n\n### What is this PR for?\r\nThis PR fixes a broken relative link in the ConfInterpreter section of the interpreter overview documentation.\r\n\r\nThe page previously linked to `../usage/interpreter/interpreter_bindings_mode.html`, but the actual interpreter binding mode document is `interpreter_binding_mode.md` and is published as `interpreter_binding_mode.html`. This updates the link to the correct relative target\r\n\r\n### What type of PR is it?\r\nDocumentation\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6498\r\n\r\n### How should this be tested?\r\n* Search the file for the broken target:\r\n ```\r\nrg -n \"interpreter_bindings_mode|\\.\\./usage/interpreter/interpreter_binding\" docs/usage/interpreter/overview.md\r\n```\r\n\r\n* Confirm `docs/usage/interpreter/interpreter_binding_mode.md` exists.\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5321 from miinhho/docs/fix-broken-interpreter-binding-link.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "63e32d74c960d138531f79487fc4bb88b56606a2",
      "tree": "d185a7f4fbc1a80468b3e6cc746e6a159cf0ea2b",
      "parents": [
        "c50b1dcad3643516d0b521e25ceec9fa730098b6"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Sun Jul 19 15:37:11 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 15:37:11 2026 +0900"
      },
      "message": "[ZEPPELIN-6471] Share a single aggregation-type constant between table and pivot\n\n### What is this PR for?\n\nThe Angular frontend hardcoded the same aggregation-type set (count, sum, min, max, avg) in two independent places — the table visualization and the pivot setting UI — with no single source of truth. The table component declared a local, unexported `AggregationType` union plus a value array; the pivot component had only an untyped `string[]` with the same values in a different order. Duplication meant the two could silently drift, and type safety was inconsistent.\n\nThis PR extracts a single shared **type** and has both components consume it, while each component keeps its own display-order array.\n\n### What changes were proposed in this PR?\n\n- Add `common/util/aggregation-type.ts` exporting `AggregationType` as the single shared type for the aggregation-type set.\n- `table-visualization.component.ts`: remove the local, unexported `AggregationType` type and import the shared one. `aggregations` keeps its existing order and is now typed `readonly AggregationType[]`.\n- `pivot-setting.component.ts`: replace the untyped `string[]` with `readonly AggregationType[]` from the shared type, keeping its existing order.\n\nBoth usages are read-only iteration/display (`\u003cat\u003efor`), so `readonly` is safe. The table\u0027s `switch (opt.aggregation)` stays exhaustive against the shared type.\n\n#### Why share the type only (not a shared value array)\n\nBoth arrays drive an aggregation dropdown in the UI:\n- pivot: `pivot-setting.component.html` `\u003cat\u003efor (aggregate of aggregates; ...)`\n- table: `table-visualization.component.html:112` `\u003cat\u003efor (aggregation of aggregations; ...)` rendered via `{{ aggregation | titlecase }}`\n\nThe two arrays use different orders. Collapsing them onto one canonical array would reorder the table column\u0027s Aggregation dropdown (Count, Sum, Min, Max, Avg → Sum, Count, Avg, Min, Max) — cosmetic, but a visible change the issue did not intend. Sharing only the type removes the duplicated/untyped definition and guarantees the two sets stay in sync, while leaving **both dropdowns exactly as they are today** — no user-visible change.\n\n### How should this be tested?\n\nThere is no frontend unit-test infrastructure in this project, so regression is confirmed via lint + build:\n\n```\ncd zeppelin-web-angular \u0026\u0026 npm run lint \u0026\u0026 npm run build:angular\n```\n\nBoth pass (0 lint errors, successful production build). Manually verified that both aggregation dropdowns are unchanged:\n- pivot setting dropdown still shows `Sum, Count, Avg, Min, Max`\n- table column Aggregation dropdown still shows `Count, Sum, Min, Max, Avg`\n\n### Questions\n\n- Does the license files need to update? No\n- Is there breaking change for older versions? No\n- Does this needs documentation? No\n\n\nCloses #5313 from kimyenac/ZEPPELIN-6471.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "c50b1dcad3643516d0b521e25ceec9fa730098b6",
      "tree": "68f1933c299405448fca226640ccd9de41469c4e",
      "parents": [
        "2e804101dfe9a3a12da1919bc08c16d190fe82ed"
      ],
      "author": {
        "name": "Manhua",
        "email": "manhua@apache.org",
        "time": "Sun Jul 19 02:06:02 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 03:06:02 2026 +0900"
      },
      "message": "[ZEPPELIN-6542] Fix missing \"Run\" menu for first paragraph in Zeppelin\n\n### What is this PR for?\r\nThe \"Run\" menu item for the first paragraph was not showing due to an incorrect show condition (!this.first). This change sets show: true unconditionally for the \"Run\" button, ensuring it is always visible for the first paragraph — which is expected behavior in Zeppelin.\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [ ] - Task\r\n\r\n### What is the Jira issue?\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6542\r\n\r\n### How should this be tested?\r\n* Strongly recommended: add automated unit tests for any new or changed behavior\r\n* Outline any manual steps to test the PR here.\r\n\r\n### Screenshots (if appropriate)\r\n\r\n### Questions:\r\n* Does the license files need to update?\r\n* Is there breaking changes for older versions?\r\n* Does this needs documentation?\r\n\n\nCloses #5307 from kevinjmh/patch-3.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "2e804101dfe9a3a12da1919bc08c16d190fe82ed",
      "tree": "e623cced5999bd976149e364626d219cf7a0a6f3",
      "parents": [
        "156cd548968d90b62e7cf262b369abd96f0c042d"
      ],
      "author": {
        "name": "HwangRock",
        "email": "157935545+HwangRock@users.noreply.github.com",
        "time": "Sun Jul 19 03:03:32 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 03:03:32 2026 +0900"
      },
      "message": "[ZEPPELIN-6546] Restore Math.max accumulation for NoteJobInfo.unixTimeLastRun\n\n### What is this PR for?\r\nJob Manager reports a wrong \"last run\" time for any note whose most recently executed paragraph is not the last paragraph in the note.\r\n\r\n`NoteJobInfo(Note)` in `JobManagerService` overwrites `lastRunningUnixTime` on every loop iteration, so the last paragraph always wins:\r\n\r\n```java\r\nlastRunningUnixTime \u003d getUnixTimeLastRunParagraph(paragraph);\r\n```\r\n\r\nConsequences:\r\n- Both UIs render and sort by `unixTimeLastRun` (`jobmanager.filter.js` in zeppelin-web, `job-manager.component.ts` in zeppelin-web-angular), so the displayed relative time and the Recently-Update sort order are wrong.\r\n- The incremental path `getNoteJobInfoByUnixTime()` filters with `unixTimeLastRun \u003e lastUpdateServerUnixTime`, so a note that just ran can be silently dropped from `LIST_UPDATE_NOTE_JOBS` pushes when an older paragraph sits at the bottom.\r\n\r\nThis is a regression of ZEPPELIN-2860, which fixed exactly this in 2017 with `Math.max` (#2543). The ZEPPELIN-3737 refactor moved the logic from NotebookServer into JobManagerService and dropped the `Math.max` (001c621c7). This PR restores it.\r\n\r\nVerified on a live server: a two-paragraph note whose first paragraph finished today and whose second paragraph was created 8 days ago and never ran showed \"8 days ago\" in Job Manager before the fix and the correct run time after.\r\n\r\n### Screenshots (if appropriate)\r\n\r\nhttps://github.com/user-attachments/assets/4508d689-2d6a-4998-bbbc-326a6006a9d9\r\n\r\n### What type of PR is it?\r\nBug Fix\r\n\r\n### Todos\r\n* [x] Restore `Math.max` accumulation in `NoteJobInfo`\r\n* [x] Regression tests\r\n\r\n### What is the Jira issue?\r\nhttps://issues.apache.org/jira/browse/ZEPPELIN-6546\r\n\r\n### How should this be tested?\r\n`mvn test -pl zeppelin-server -Dtest\u003dJobManagerServiceTest` — the two new tests pin `unixTimeLastRun` to the max paragraph timestamp via the `getNoteJobInfoByUnixTime` filter boundary and fail without the fix.\r\n\r\nManually: create a note with two paragraphs, run only the first one, open the Job Manager page. Before the fix the note shows the second paragraph\u0027s creation date as its last run and sorts accordingly; after the fix it shows the actual run time.\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\r\n\n\nCloses #5319 from HwangRock/ZEPPELIN-6546.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "156cd548968d90b62e7cf262b369abd96f0c042d",
      "tree": "95d7994631fc7d4e8a6b687176732b5de1c2a30d",
      "parents": [
        "386d110c089fb26bbbe6d61b30dd395c6c181037"
      ],
      "author": {
        "name": "Gyeongtae Park",
        "email": "gyeongtae@apache.org",
        "time": "Sun Jul 19 02:49:09 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 02:49:09 2026 +0900"
      },
      "message": "[ZEPPELIN-6541] Pin maven-checkstyle-plugin version so it is actually applied\n\n### What is this PR for?\r\nThe root `pom.xml` declares a `plugin.checkstyle.version` property (`2.17`) intended to pin the `maven-checkstyle-plugin` version used across all modules, but the plugin\u0027s `\u003cpluginManagement\u003e` declaration never referenced it via a `\u003cversion\u003e` tag. As a result Maven silently resolved a different, non-deterministic plugin version regardless of what the property said — confirmed locally: the property said `2.17`, but the build actually ran `checkstyle:3.4.0:check`. This PR adds the missing `\u003cversion\u003e${plugin.checkstyle.version}\u003c/version\u003e` tag and bumps the property to `3.6.0` (the current latest release) so the pinned version is the one that actually runs.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### Todos\r\n* [x] Add `\u003cversion\u003e${plugin.checkstyle.version}\u003c/version\u003e` to the `maven-checkstyle-plugin` block in `\u003cpluginManagement\u003e`\r\n* [x] Bump `plugin.checkstyle.version` from `2.17` to `3.6.0`\r\n\r\n### What is the Jira issue?\r\n[ZEPPELIN-6541](https://issues.apache.org/jira/projects/ZEPPELIN/issues/ZEPPELIN-6541)\r\n\r\n### How should this be tested?\r\n```bash\r\n./mvnw -pl shell verify -DskipTests\r\n```\r\nConfirm the log shows checkstyle:3.6.0:check (not an arbitrary/older version) and the build completes with BUILD SUCCESS. No module overrides the plugin version locally, so all modules using maven-checkstyle-plugin inherit the pinned version consistently.\r\n\r\n\r\nScreenshots (if appropriate)\r\n\r\nN/A\r\n\r\nQuestions:\r\n\r\n- Does the license files need to update? No.\r\n- Is there breaking changes for older versions? No — build-time only change, no runtime behavior affected.\r\n- Does this needs documentation? No.\n\nCloses #5308 from ParkGyeongTae/ZEPPELIN-6541.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "386d110c089fb26bbbe6d61b30dd395c6c181037",
      "tree": "f6d013782d372cd4aa16a4c241b1cbbcccb8bf43",
      "parents": [
        "108536f4e0eef785ba855927a94701627d333d98"
      ],
      "author": {
        "name": "YONGJAE LEE (이용재)",
        "email": "dev.yongjaelee@gmail.com",
        "time": "Sun Jul 19 02:24:53 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 02:24:53 2026 +0900"
      },
      "message": "[ZEPPELIN-6544] Harden keyboard-shortcut e2e helpers against silent passes\n\n### What is this PR for?\r\nFollow-up to ZEPPELIN-6536 (#5304). A cross-review of the merged keyboard-shortcut suite found four silent-pass risks in the helpers; this PR closes them:\r\n\r\n- `pressShortcutFromHostUntil` now polls for the press\u0027s effect before retrying, so a slow toggle is not double-pressed and the loop cannot return on the transient state between two in-flight effects.\r\n- The clear-output test asserts the result is visible before pressing; previously a no-output run let the helper skip the press entirely.\r\n- InsertAbove/InsertBelow emptiness assertions now gate on the editor being rendered (`waitForEditorRendered`); an unrendered editor reads as `\u0027\u0027` and matched vacuously.\r\n- `setCodeEditorContent` compares normalized equality instead of containment, so stale fixture text fails at seeding time.\r\n\r\nTest-only change; no product code touched.\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\nZEPPELIN-6544\r\n\r\n### How should this be tested?\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? No\n\nCloses #5315 from voidmatcha/fix/harden-keyboard-e2e-helpers.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "108536f4e0eef785ba855927a94701627d333d98",
      "tree": "ef55c4706cae86ec67cb2632bf7bec11e217ac96",
      "parents": [
        "adea3b955148eb9c7f990e682309261fec660099"
      ],
      "author": {
        "name": "김예나",
        "email": "101786858+kimyenac@users.noreply.github.com",
        "time": "Sun Jul 19 02:06:59 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 02:06:59 2026 +0900"
      },
      "message": "[ZEPPELIN-6534] Escape note name before building clone-name RegExp\n\n### What is this PR for?\n\nCloning a note whose name contains a regular-expression metacharacter (for example `[`, `(`, or a trailing backslash) threw an uncaught `SyntaxError` when the clone dialog opened, so the suggested clone name was never generated and the dialog was broken for that note. `cloneNoteName()` interpolated the note name directly into a `RegExp` source without escaping it. This PR escapes the note name before building the `RegExp`, so any note name is matched literally.\n\nWhile verifying the fix in the running UI, a second, pre-existing defect surfaced in the same note view: opening **any** note logged an uncaught `TypeError: Cannot read properties of undefined (reading \u0027forEach\u0027)`. In `ngOnInit`, the `queryParamMap` subscription runs synchronously via `startWith()` and calls `onParagraphSearch()` before the `\u003cat\u003eViewChildren` `QueryList` (`listOfNotebookParagraphComponent`) is populated (it is only available after `ngAfterViewInit`). This PR guards that call with optional chaining, consistent with the existing null handling elsewhere in the same component. It is included here as a small drive-by fix, in its own commit so it can be split out if preferred.\n\n### What type of PR is it?\n\nBug Fix\n\n### Todos\n\n* [x] Escape note name before building the clone-name `RegExp`\n* [x] Guard `onParagraphSearch()` against an uninitialized `\u003cat\u003eViewChildren` `QueryList`\n\n### What is the Jira issue?\n\n[ZEPPELIN-6534](https://issues.apache.org/jira/browse/ZEPPELIN-6534)\n\n### How should this be tested?\n\n* `cd zeppelin-web-angular \u0026\u0026 npm run lint`\n* Create a note named `report[2024` (or `foo(bar`) and click **Clone**: before the fix the dialog throws `SyntaxError` and no name is suggested; after the fix it suggests `report[2024 1` and clones normally. Clone-name numbering for ordinary names is unchanged (escaping is a no-op when there are no metacharacters).\n* Open any note with the browser devtools console open: before the fix a `forEach` `TypeError` is logged on load; after the fix the console is clean.\n\n### Questions:\n\n* Does the license files need to be updated? No\n* Are there breaking changes for older versions? No\n* Does this need documentation? No\n\n\nCloses #5318 from kimyenac/ZEPPELIN-6534.\n\nSigned-off-by: ChanHo Lee \u003cchanholee@apache.org\u003e"
    },
    {
      "commit": "adea3b955148eb9c7f990e682309261fec660099",
      "tree": "1dff4d7bad9d13d02cef4a8a21e1f5a324d4fea9",
      "parents": [
        "9245bbb6bf4b74d36959b0335ee2958b0542b984"
      ],
      "author": {
        "name": "Minho Jang",
        "email": "166613620+miinhho@users.noreply.github.com",
        "time": "Sat Jul 18 11:03:34 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 11:03:34 2026 +0900"
      },
      "message": "[ZEPPELIN-6545] Move the classic-suite gating to a dedicated Playwright config\n\n### What is this PR for?\r\n\r\nThis PR separates the classic UI Playwright e2e suite from the main Playwright config.\r\n\r\nAfter ZEPPELIN-6527, classic specs under `e2e/tests/classic/` were wired into the shared config and gated with `E2E_CLASSIC` plus argv sniffing. That made plain `npm run e2e` depend on a `-Pweb-classic` server, allowed false positives from arguments like `--grep tests/classic`, and caused the coverage reporter to run for classic pages that are outside the coverage denominator.\r\n\r\nThis change moves classic execution to a dedicated `playwright.classic.config.js`, updates `e2e:classic` and CI wiring to use it, removes the env/argv detection from the main config, and keeps the coverage reporter on the main suite only.\r\n\r\n\r\n### What type of PR is it?\r\nImprovement\r\n\r\n### What is the Jira issue?\r\n* https://issues.apache.org/jira/browse/ZEPPELIN-6545\r\n\r\n### How should this be tested?\r\n- `cd zeppelin-web-angular \u0026\u0026 npm run e2e -- tests/classic --list --reporter\u003dlist`\r\n  - Verifies the main Playwright config no longer selects classic specs.\r\n- `cd zeppelin-web-angular \u0026\u0026 npm run e2e:classic -- --list --reporter\u003dlist`\r\n  - Verifies classic specs are selected only through the dedicated classic config.\r\n- `rg \"E2E_CLASSIC|process\\\\.argv|isClassicOnlyRun|E2E_MODE\" zeppelin-web-angular .github/workflows/frontend.yml`\r\n  - Verifies the old env/argv gating was removed.\r\n- `rg \"reporter\\\\.coverage\" zeppelin-web-angular/playwright.config.js zeppelin-web-angular/playwright.classic.config.js`\r\n  - Verifies the coverage reporter is only configured for the main suite.\r\n\r\n\r\n### Questions:\r\n* Does the license files need to update? No\r\n* Is there breaking changes for older versions? No\r\n* Does this needs documentation? Edit AGENTS.md about modified classic suite config\r\n\n\nCloses #5317 from miinhho/test/move-classic-suite-gate.\n\nSigned-off-by: YONGJAE LEE \u003cdev.yongjaelee@gmail.com\u003e"
    }
  ],
  "next": "9245bbb6bf4b74d36959b0335ee2958b0542b984"
}
