)]}'
{
  "log": [
    {
      "commit": "45d6050df5ba10b2ec76ce90d41fa4c7367a218a",
      "tree": "08e15d2c9ac0f8a7fa4f232297f64d277d3a2d55",
      "parents": [
        "b10d094dadb4f4b587aa52c4ce2dd357ebf4f952"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Wed Jul 01 00:48:20 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 01 00:48:20 2026 -0400"
      },
      "message": "Access-scoped server endpoints + generated-only Python SDK (#697)\n\nServer + SDK groundwork so the Django portal (and any client) can run on raw gRPC with no Python SDK facade.\n\n- **server**: additive `*WithAccess` reads + composite/reconciled write endpoints across research / compute / storage / credential / iam — server-computed access flags, `GetFullExperiment`, `SearchExperimentsWithAccess`, `SetEntitySharing` + SharedEntity composites, reconciled group \u0026 group-resource-profile writes, `LaunchExperimentWithStorageSetup`, `CloneExperimentWithInputFiles`, `CopyFile` / `DownloadDataProduct`.\n- **server**: ExperimentSet service — define-from-spec, sweep expansion, persistence (+ V1 baseline tables).\n- **iam**: user-preferences service — most-recent project / GRP / compute selections + per-app favorites.\n- **sdk**: thin generated-only `airavata` package over the server stubs; delete the facade / helpers / clients; codegen folded into a uv script.\n- **keycloak**: restore `pga-public` to a public PKCE client (drop the `authorizationSettings` block that forced it confidential and broke portal login)."
    },
    {
      "commit": "b10d094dadb4f4b587aa52c4ce2dd357ebf4f952",
      "tree": "4f4f465ea28dcd3193e4146cf1975f55dac0db34",
      "parents": [
        "ce471241bc57c4ca36e8847468cff1e0481af91c"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 20 18:31:27 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 18:31:27 2026 -0400"
      },
      "message": "Token-authoritative auth: derive caller identity from the verified Keycloak token (#695)\n\n* feat(auth): derive caller identity from the verified access token\n\nEstablish identity solely from the signature-verified Keycloak token instead of\ntrusting client-supplied x-claims headers, and reject tokens that fail verification.\n\n- JwtVerifier.verify() returns a VerifiedToken (userName from preferred_username,\n  gatewayId from the issuer realm, realm roles) and throws TokenVerificationException\n  on a missing, malformed, expired, or unverifiable token.\n- GrpcAuthInterceptor and HttpAuthDecorator reject such requests with\n  UNAUTHENTICATED / 401 instead of proceeding as a non-admin.\n- AuthTokenExtractor builds the AuthzToken claims map from the verified token only;\n  x-claims, x-user-name, and x-gateway-id are no longer read.\n\nA Keycloak access token is now sufficient on its own to call the API: every client\n(browser SPA, SDK, portal) is authenticated and identified identically, and identity\ncan no longer be asserted via headers. UserContext and its readers are unchanged.\n\nAdds VerifiedToken, TokenVerificationException, and JwtVerifierTest.\n\n* feat(sdk): send only the Keycloak access token for auth\n\nThe server now derives identity from the verified token, so the client no longer\nsends x-claims. AiravataClient sends the access token as a Bearer credential only and\ndecodes username/gateway from the token locally for convenience.\n\n* build(tilt): clean install in the build step\n\nRun `mvn clean install` so a stale target/ (e.g. orphaned protobuf-generated\nsources after a proto refactor) cannot break the Tilt build.\n\n* feat(sdk): token-only auth across all client and transport paths\n\nExtend the token-only change to the remaining SDK surfaces so a Keycloak access\ntoken is the sole credential everywhere and no client-asserted identity is sent:\n\n- clients/*.py (14 service clients) and transport/utils.py no longer append the\n  x-claims metadata.\n- airavata_experiments/plan.py and airavata_jupyter_magic no longer send the\n  X-Claims header; the now-dead claims-building is removed.\n\nThe server derives identity from the verified token, so x-claims was redundant.\n\n* feat(keycloak): add pga-public client (public, PKCE) for browser OIDC\n\nA public PKCE client for the portal SPA to run the Authorization Code + PKCE flow\nin the browser, so identity is obtained from Keycloak client-side and the access\ntoken is sent to airavata directly. Confidential `pga` client is unchanged."
    },
    {
      "commit": "ce471241bc57c4ca36e8847468cff1e0481af91c",
      "tree": "5c176844965d9ab66464c320aa2ec8dc4540c95b",
      "parents": [
        "6edb39c1a26fd2bcc9e454162a562811a03cd32a"
      ],
      "author": {
        "name": "lahiruj",
        "email": "lahirujayathilake@gmail.com",
        "time": "Thu Jun 18 17:30:58 2026 -0400"
      },
      "committer": {
        "name": "lahiruj",
        "email": "lahirujayathilake@gmail.com",
        "time": "Thu Jun 18 17:30:58 2026 -0400"
      },
      "message": "null-safe ExperimentSummary view\n"
    },
    {
      "commit": "6edb39c1a26fd2bcc9e454162a562811a03cd32a",
      "tree": "75382d7b63fc8c8401a4b33d68eeebde5041cff6",
      "parents": [
        "5a62c0f4295704bc4fc811af65bc4e954d7738f7"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Jun 15 00:29:17 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 15 00:29:17 2026 -0400"
      },
      "message": "feat(research): short, human-readable experiment ids (EXP-XXXXXXXX) (#694)\n\nExperiment ids were sanitize(name)[:50] + \"_\" + UUID, e.g.\nEcho_on_Jun_14,_2026_9:36_PM_96aa3cbd-..., which mashed the name and a uuid into\nthe primary key and the portal URL. Generate a short, URL-safe, collision-checked\ncode instead (e.g. EXP-7QK2F9MX) via AiravataUtils.getReadableId, keeping the name\nas the separate experiment_name field. Only new experiments are affected; the id\nstays a varchar PK so existing ids and all FK references keep working. The portal\nalready routes by experiment_id, so URLs become /workspace/experiments/EXP-7QK2F9MX/\nwith no portal change.\n\nThe two tests that asserted the id embeds the normalized name now assert the new\ncontract: a short EXP- code, with the experiment name preserved verbatim."
    },
    {
      "commit": "5a62c0f4295704bc4fc811af65bc4e954d7738f7",
      "tree": "703f391d71a7229363767418441c88a4a83ef6d5",
      "parents": [
        "49dcf411d5f26c1062c114f2f8f7ed2f54f7bacb"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 14 20:07:19 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 14 20:07:19 2026 -0400"
      },
      "message": "fix(keycloak): stop forcing \u0027airavata\u0027 as the global default theme (#693)\n\nThe devstack set --spi-theme-default\u003dairavata, but the airavata theme only ships\na login variant. That also made airavata the default ACCOUNT theme, so Keycloak\u0027s\naccount console returned HTTP 500 with a NullPointerException (account theme\n\u0027airavata\u0027 not found) — breaking the portal\u0027s User Settings link. The default\nrealm already pins loginTheme: airavata, so removing the global default keeps\nlogin branding intact while account/admin/email fall back to Keycloak\u0027s built-in\nthemes."
    },
    {
      "commit": "49dcf411d5f26c1062c114f2f8f7ed2f54f7bacb",
      "tree": "7edbe9068c1ff6ecb0c9c08f0ab04807f12dc61d",
      "parents": [
        "2c15f2cb234cebfbd138e148cb99e622deff74d9"
      ],
      "author": {
        "name": "yasithdev",
        "email": "yasith.j@icloud.com",
        "time": "Sun Jun 14 13:05:42 2026 -0400"
      },
      "committer": {
        "name": "yasithdev",
        "email": "yasith.j@icloud.com",
        "time": "Sun Jun 14 13:05:42 2026 -0400"
      },
      "message": "fix(slurm): resolve compute NodeAddrs on startup so batch jobs run on the allocated node\n\nExperiments failed during execution: environment setup and job submission\nsucceeded and the job went active, but once it finished both the job and the\nmonitoring task flipped to FAILED.\n\nRoot cause is in the devstack SLURM cluster, not the orchestrator. slurmctld\nresolves each node\u0027s NodeAddr exactly once, when it reads slurm.conf at startup.\nIn the compose stack the controller can come up before the compute containers\nare DNS-resolvable (or while a prior run\u0027s container IPs are still cached), so it\nlatches onto a stale/crossed NodeName -\u003e IP mapping and keeps it for its whole\nlifetime. Batch-job launches for a job allocated to c1 were then delivered to\nc2\u0027s slurmd, which rejects them (\"Host c2 not in hostlist c1\"); slurmctld reads\nthat as a node failure and requeues the job until it is held\n(JobHoldMaxRequeue), so jobs never actually run to completion. (srun and getent\nlooked fine because they resolve live; only the controller\u0027s cached batch path\nwas affected.) A single `scontrol reconfigure` re-resolves every NodeAddr and\nrestores correct routing.\n\nChanges:\n\n- conf/slurm/docker-entrypoint.sh: the slurmctld role now backgrounds a small\n  reconciler that waits for the controller and every configured compute node to\n  be resolvable, then issues one `scontrol reconfigure` to re-resolve all\n  NodeAddrs against current DNS. Self-heals the startup race on every boot;\n  harmless when addresses were already correct.\n\n- MonitoringTask: distinguish an infrastructure failure that SLURM requeues\n  (NODE_FAIL / BOOT_FAIL) from a genuinely terminal failure, and ride out a\n  short grace window before treating a sustained absence as failure, so a\n  transient infra hiccup is tracked through the job lifecycle instead of\n  aborting the experiment. The JOB_SUBMISSION -\u003e MONITORING task structure is\n  unchanged.\n\nTest plan:\n\n- Cold start (full slurm image rebuild + container recreate): the reconciler\n  runs and logs the re-resolve; fresh batch jobs route correctly (c1 -\u003e c1,\n  c2 -\u003e c2) with zero wrong-node errors.\n- End-to-end Echo experiment via the portal completes (environment setup -\u003e\n  job submission -\u003e monitoring -\u003e data staging) with output staged back; the\n  SLURM job reaches COMPLETED on its allocated node.\n"
    },
    {
      "commit": "2c15f2cb234cebfbd138e148cb99e622deff74d9",
      "tree": "82da8aba214f611a4cf792e6df43afe6d10b416a",
      "parents": [
        "ae8c3d5aa4ec0a16290919cc1aaf656651bac4f5"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 14 02:57:32 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 14 02:57:32 2026 -0400"
      },
      "message": "feat(echo): add a configurable experiment duration to the dev Echo app (#691)\n\nAdd an Experiment_Duration input (default 60s) to the Echo application interface and route the deployment through a new echo_sleep wrapper that sleeps for the given duration before echoing the message. This lets Echo runs last long enough to exercise and observe the experiment progress pipeline."
    },
    {
      "commit": "ae8c3d5aa4ec0a16290919cc1aaf656651bac4f5",
      "tree": "06878b605ce07c953e23c8c08f4949976b5b789d",
      "parents": [
        "a8ce2ce51613a183d88a7cd9c3561c1402806397"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 14 02:57:30 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 14 02:57:30 2026 -0400"
      },
      "message": "fix(devstack): make reset a true wipe and retry the ingress check (#690)\n\ndevstack reset only ran `colima delete`, but colima keeps a persistent Lima data disk under _lima/_disks/\u003cinstance\u003e (bind-mounted to /var/lib/docker) that survives the delete, so images, volumes and restart:unless-stopped containers resurrected on the next VM start. Remove that disk so reset is a true from-scratch wipe.\n\nAlso wrap the verify gate\u0027s :443 check in a short retry loop so a freshly pulled / cold Traefik does not spuriously fail it."
    },
    {
      "commit": "a8ce2ce51613a183d88a7cd9c3561c1402806397",
      "tree": "6a2c029cff67b8583ebd4a1d187c5dea853023d3",
      "parents": [
        "b379c3956a607ec798bd7577350dc209168e3e32"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 23:36:29 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 23:36:29 2026 -0400"
      },
      "message": "feat(auth): verify access tokens and enforce gateway-admin roles server-side (#688)\n\nThe server previously trusted the bearer token without verifying its signature\nand enforced no coarse admin check, relying entirely on the portal. Verify the\nKeycloak access token (RS256 against the realm JWKS, exp, issuer) at the shared\nAuthTokenExtractor seam and extract realm_access.roles into the RequestContext;\nroles are only trusted from a signature-verified token, so a forged token\nresolves to a non-admin. Add an AdminAccess guard (admin-rw / admin-ro) and apply\nit to the gateway-wide admin operations: IAM user listing, experiment statistics,\nand getExperimentByAdmin. Per-entity sharing ACLs are unchanged.\n\nAlso fixes GrpcStatusMapper, which only matched \u0027AuthorizationException\u0027 and so\nmapped the 63 ServiceAuthorizationException sites to INTERNAL instead of\nPERMISSION_DENIED."
    },
    {
      "commit": "b379c3956a607ec798bd7577350dc209168e3e32",
      "tree": "d84490b997977c3eee329996f02a3b227e702ea3",
      "parents": [
        "237472792795c5792ce468b47a6c7953d9c77950"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 22:39:33 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 22:39:33 2026 -0400"
      },
      "message": "seed: register dev SFTP credential as sharing entity; set gateway default token (#687)\n\nThe seeded SFTP credential token had a credentials-store row but no sharing\nregistry entity, so getAllCredentialSummaries (sharing-scoped) returned nothing\nand /admin/credentials was empty; the gateway resource profile likewise showed\nno default SSH credential. Add the CREDENTIAL_TOKEN sharing entity + OWNER grant\nfor default-admin (mirroring generateAndRegisterSSHKeys), and set\ngateway_profile.CS_TOKEN to the token."
    },
    {
      "commit": "237472792795c5792ce468b47a6c7953d9c77950",
      "tree": "7131a8b22422e1efaefbe166f7f23d46350bf1d0",
      "parents": [
        "c20929fd4dafed81e3430aeaac462392077d3b00"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 22:32:30 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 22:32:30 2026 -0400"
      },
      "message": "refactor(iam): rename provisioning roles to admin-rw/admin-ro/user (#686)\n\nAlign the Keycloak provisioning code with the renamed realm roles:\ncreateDefaultRoles now defines admin-rw / admin-ro / user (was admin /\nadmin-read-only / gateway-user) and createTenantAdminAccount grants the gateway\nadmin the admin-rw role. Keeps newly-provisioned gateways consistent with the\ndev realm\u0027s role vocabulary."
    },
    {
      "commit": "c20929fd4dafed81e3430aeaac462392077d3b00",
      "tree": "e6993d69611d085a5d04b1fc8bf9529ee339fc2d",
      "parents": [
        "0a0473010bf58e1f58489167ac985ae8d73b0eea"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 22:28:41 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 22:28:41 2026 -0400"
      },
      "message": "seed(keycloak): grant default-admin realm-management roles (#685)\n\nThe dev realm\u0027s default-admin had the admin-rw role but no realm-management\nclient roles, so server-side IAM operations that call the Keycloak admin API\nwith the admin\u0027s token (e.g. IamAdminService.getUsers backing /admin/users)\nreturned HTTP 403. Production gateway admins receive all realm-management roles\nvia createTenantAdminAccount; mirror that for the dev admin by granting the\nrealm-management realm-admin composite."
    },
    {
      "commit": "0a0473010bf58e1f58489167ac985ae8d73b0eea",
      "tree": "e79a08d440d09f411f768ccfa788067cf3e2dd44",
      "parents": [
        "5688a8a14a7ab10dcf8f7abc5dc8bde6a3b9deb7"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 22:24:38 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 22:24:38 2026 -0400"
      },
      "message": "fix(research): ignore blank experiment-statistics filters (#684)\n\nThe statistics gRPC handler forwards the proto userName, applicationName and\nresourceHostName fields verbatim, and unset proto strings default to \"\" rather\nthan null. filterExperimentStatisticsQuery only skipped null values, so an unset\nfield became a literal ES.userName \u003d \u0027\u0027 (etc.) predicate that matched no rows —\nthe admin experiment-statistics page, which sends none of these, always returned\nzero. Guard each optional string filter against blank."
    },
    {
      "commit": "5688a8a14a7ab10dcf8f7abc5dc8bde6a3b9deb7",
      "tree": "cd1a08afdef0532d0cad8611dd2f0550ab8f36e3",
      "parents": [
        "1c96d1c2f9be68b2947cc7ee2d847bd6303ddc83"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 22:06:57 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 22:06:57 2026 -0400"
      },
      "message": "seed(keycloak): rename gateway roles to admin-rw/admin-ro/user; grant default-admin admin-rw (#683)\n\nRename the dev realm\u0027s coarse-authorization roles (admin-\u003eadmin-rw,\nadmin-read-only-\u003eadmin-ro, gateway-user-\u003euser), add `user` to the realm\ndefault-role composite so every authenticated user inherits it, and grant\ndefault-admin the admin-rw role. First step of moving gateway-admin\ndetermination from the sharing-registry group lookup to Keycloak realm roles\ncarried in the JWT."
    },
    {
      "commit": "1c96d1c2f9be68b2947cc7ee2d847bd6303ddc83",
      "tree": "72b0905c4edc6d6a46a88145e2c83d72ef915667",
      "parents": [
        "b2175d20f6a289c786410b96560285dd1a706fa6"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 16:16:21 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 16:16:21 2026 -0400"
      },
      "message": "refactor(api): remove dead schema, fix two persistence defects, drop legacy fields (#682)\n\nRemoves schema no code reads (process_workflow table+proto, resource.status/StatusEnum, orphan agent_deployment_info table, unused BatchQueueRepository, duplicate app_module_mapping entity mapping, dead credentials.CREDENTIAL_OWNER_TYPE column, and the grid-cert-legacy user_dn/generate_cert fields on ProcessModel/UserConfigurationDataModel with proto numbers reserved and Python stubs regenerated). Fixes two defects: parsing_template silently dropped its parser_connections DAG on save, and queue_status.RUNNING_JOBS was a bit(1) truncating the running-job count to 0/1 (now int). Adds UNIQUE constraints on tag(value) and resource_star(user_id, resource_id) with race-safe idempotent find-or-create. Entities and both V1 baselines stay in sync; verified with a clean build and a fresh-DB init of schema + seed."
    },
    {
      "commit": "b2175d20f6a289c786410b96560285dd1a706fa6",
      "tree": "1f84ba755bc390931e23d50e0b23c33a54d9ece0",
      "parents": [
        "f66bdc1253a6b7272d37e6513c56079513a8e212"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 11:45:50 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 11:45:50 2026 -0400"
      },
      "message": "Remove residual dead code: orphaned ServerSettings config + migration CLI (#681)\n\n- Drop the six ServerSettings accessors orphaned when the Helix-era classes were\n  removed (getReSchedulerPolicyClass, getDataAnalyzingEnabledGateways,\n  getDataAnalyzerTimeStep, getDataAnalyzerScanningInterval,\n  getDataAnalyzerNoOfScanningParallelJobs, getMetaschedulerReschedulingThreshold)\n  and their six now-unused config-key constants (data.analyzer.*, the rescheduler\n  policy class, and the metascheduler reschedule threshold). All verified\n  zero-caller; getReSchedulerPolicyClass even defaulted to a since-deleted class.\n- Delete MigrateCredentialEncryption, a standalone main() CLI for the spent\n  one-time CBC-\u003eGCM credential re-encryption (no callers, no build wiring)."
    },
    {
      "commit": "f66bdc1253a6b7272d37e6513c56079513a8e212",
      "tree": "2b88e79a642ecca159e5d63b73085caaffb1b170",
      "parents": [
        "e10475ccee0407ffc03f5c7f3233d99c850fcdb7"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 11:32:15 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 11:32:15 2026 -0400"
      },
      "message": "Remove orphaned method, debug main()s, and stale plugin pins (#680)\n\n- AgentExperimentService.getUserExperimentIDs(): zero callers — orphaned when the\n  FuseService removal deleted its only consumer.\n- Four debug/demo public static void main() methods embedded in live production\n  classes (DefaultComputeResourceSelectionPolicy, LSFOutputParser,\n  TenantManagementKeycloakImpl, NameValidator) — the host classes stay.\n- Two stale pluginManagement pins for abandoned tooling (com.dkanejs\n  docker-compose-maven-plugin, io.fabric8 docker-maven-plugin) that no module\n  activates."
    },
    {
      "commit": "e10475ccee0407ffc03f5c7f3233d99c850fcdb7",
      "tree": "bb4fe83d4853b79bfa48238d0f782c27d16b3dbc",
      "parents": [
        "114720011ba4553cfc0992167627ea616a16404a"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 11:25:55 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 11:25:55 2026 -0400"
      },
      "message": "Remove Helix/gfac-era dead orchestration code (#679)\n\nThirty unreferenced classes under orchestration-service/task plus email-config.yaml,\nall leftover scaffolding from the pre-DB-transactional-executor (Helix/gfac) era —\na closed set that nothing live references (the reactor compiles cleanly without it):\n\n- Email-monitor parsing: EmailParser + PBS/SLURM/UGE/LSF/HTCondor/AiravataCustom\n  parsers + ResourceConfig + email-config.yaml (live monitoring uses squeue polling;\n  ServerSettings.getEmailBasedMonitorAddress, still used by GroovyMapBuilder, is kept).\n- IServer lifecycle + its three impls (DataInterpreterService,\n  ProcessReschedulingService, ComputationalResourceMonitoringService) + DataAnalyzer(Impl).\n  The impls carry no Spring stereotype, so component-scan never instantiated them.\n- Process scanner/scheduler/rescheduler cluster (ProcessScanner(Impl),\n  ProcessScheduler(Impl), ReScheduler, ExponentialBackOffReScheduler).\n- Orphaned leaves: AbstractMonitor, RealtimeJobStatusParser, JobStateValidator,\n  ParsingTaskInput/Inputs/Output/Outputs, AnalyzerConstants, SchedulerConstants,\n  ProcessCompletionMessage."
    },
    {
      "commit": "114720011ba4553cfc0992167627ea616a16404a",
      "tree": "ae46946c1e2e37f38a4ca10028472d08dea33ba7",
      "parents": [
        "280b18c3ad13f8a9842a922cbd8b9dc1f3251b10"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 10:57:41 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 10:57:41 2026 -0400"
      },
      "message": "Tidy airavata-api dependencies (drop unused snakeyaml, relocate groovy/mail) (#678)\n\n- Drop the explicit snakeyaml dependency from airavata-api (0 imports); it stays\n  available transitively via spring-boot, so the resolved tree is unchanged.\n- Relocate two dependencies to the modules that actually use them: groovy-templates\n  -\u003e compute-service (its only importer) and spring-boot-starter-mail -\u003e\n  orchestration-service (its only importer), instead of declaring them in airavata-api.\n\nThe airavata-server fat jar still resolves groovy-templates, spring-boot-starter-mail,\nand snakeyaml (verified via dependency:list); the full reactor compiles."
    },
    {
      "commit": "280b18c3ad13f8a9842a922cbd8b9dc1f3251b10",
      "tree": "d43b6a9670932d13ef877e0fd09fbc80c9f7074c",
      "parents": [
        "ea4424ecc6fb3a7ac94527ab82bd43d474dd0059"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:49:07 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:49:07 2026 -0400"
      },
      "message": "Remove dead dependencyManagement version pins (#677)\n\nTen dependencyManagement entries and the selenium-maven-plugin pluginManagement\nentry pinned artifacts that appear nowhere in the resolved dependency tree, so\nthe pins were inert: dozer-core, the four selenium-* drivers, json-simple,\ncommons-exec, mysql-connector-j (the DB driver is mariadb-java-client),\nkeycloak-authz-client (IAM uses keycloak-admin-client), and slf4j-simple.\ncommons-logging and jcl-over-slf4j are kept — both are live in the tree.\nVerified via dependency:list; reactor resolves and compiles unchanged."
    },
    {
      "commit": "ea4424ecc6fb3a7ac94527ab82bd43d474dd0059",
      "tree": "f472a3d385fe8b2718471479c98e6e8952b689d4",
      "parents": [
        "bd5e06d924e7a5ba024382ce4e641f58f45313d1"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:44:38 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:44:38 2026 -0400"
      },
      "message": "Drop inaccurate \"Return Path\" docstring boilerplate from SDK file ops (#676)\n\nThe line \"Return Path: /{project_name}/{experiment_name}\" was copy-pasted into six\nairavata_experiments file-operation docstrings (upload/list/download/etc.) where it\ndoes not describe the actual return value — only make_experiment_dir returns that\npath, and its first docstring line already says so. Remove the boilerplate."
    },
    {
      "commit": "bd5e06d924e7a5ba024382ce4e641f58f45313d1",
      "tree": "dd2efd2b9aed83f5ddce6727b5998958a4c7ed23",
      "parents": [
        "e0c50804e14121162aba39153fbc10899d7cd708"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:42:47 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:42:47 2026 -0400"
      },
      "message": "Remove unused research config (portal-url / dev-url / dev-user) (#675)\n\nResearchProperties bound airavata.research.portal-url, dev-url, and dev-user from\napplication.properties, but nothing reads getPortalUrl/getDevUrl/getDevUser\n(0 readers). Remove the three fields and their getters/setters, the matching\napplication.properties lines, and the two orphaned research_portal_url /\nresearch_portal_dev_url example vars in the ansible vault template (no .j2\nconsumed them). hub-url, admin-api-key, and limit stay (live)."
    },
    {
      "commit": "e0c50804e14121162aba39153fbc10899d7cd708",
      "tree": "387bed0776e3340063e54d5186d22bef382f33bb",
      "parents": [
        "70ff6c249c72301e43334469078682cb9fc46d38"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:34:19 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:34:19 2026 -0400"
      },
      "message": "Remove dead FuseService subsystem (#674)\n\nThe FUSE gRPC contract was never wired to any client. Remove airavata-fuse.proto\n(the FuseService with 8 stub RPCs), its only impl FuseFSHandler (a @Component\nBindableService that returned hardcoded dummies and is auto-collected into the\nArmeria gRPC service list, so it self-deregisters), the never-invoked\nAiravataFileService and its model types (ExperimentStorageResponse, DirectoryInfo,\nFileInfo), and the three committed SDK fuse stubs. ServiceWiringConfig drops the\nAiravataFileService/AgentExperimentService wiring that existed solely to feed the\ndead read-dir path. No Go agent or SDK/portal client references FuseService."
    },
    {
      "commit": "70ff6c249c72301e43334469078682cb9fc46d38",
      "tree": "5ced60eeb797497f973b8b70029ff453e9c4f63f",
      "parents": [
        "60d7f2df43616b06b2a647955a691888a2c9287f"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:19:58 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:19:58 2026 -0400"
      },
      "message": "Remove dead messaging_events.proto and its orphaned SDK stubs (#673)\n\nmessaging_events.proto (16 Thrift-era event messages: Experiment/Process/Task/Job\nstatus-change and submit/terminate events, plus the generic Message envelope) is\nimported by no other proto and referenced by no hand-written Java/Python — its\nonly consumer, KafkaProxyService, was removed when orchestration moved to the\nDB-transactional executor. Remove it and its three committed SDK stubs. Protos\nare glob-compiled, so the reactor regenerates cleanly without it."
    },
    {
      "commit": "60d7f2df43616b06b2a647955a691888a2c9287f",
      "tree": "5557ae7712b38565698b9770363db31b5f954c15",
      "parents": [
        "d9243eef765ebb4678664cda0a82fe76b195ae16"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:17:40 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:17:40 2026 -0400"
      },
      "message": "Drop placeholder class javadoc and fix corrupted license header (#672)\n\nRemove the boilerplate \"TODO: Class level comments please\" placeholder javadoc\n(the template `@author dimuthu / @since 1.0.0-SNAPSHOT` block) from 10 task/\nand compute/util classes — it adds no information. Also fix the ASF license\nheader in file_handling_client.py, whose first line was mangled by a stray\nfind/replace (\"Licrecursive\u003dNonepache\" -\u003e \"Licensed to the Apache\")."
    },
    {
      "commit": "d9243eef765ebb4678664cda0a82fe76b195ae16",
      "tree": "1ea9d8ea957048615af7b0ef3549597d40acb94d",
      "parents": [
        "20076b36fd6c457277d96b02e062442d97f7af2b"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:13:41 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:13:41 2026 -0400"
      },
      "message": "Remove unused docker-java dependency (#671)\n\ndocker-java (and its three docker-java-* version pins in the root\ndependencyManagement) is declared but never imported anywhere — 0 references.\nIt pulled a large jersey/netty subtree (hence the long exclusion list). Removing\nit slims the dependency tree; the reactor compiles and resolves cleanly without\nit, and docker-java is absent from the resolved tree afterward."
    },
    {
      "commit": "20076b36fd6c457277d96b02e062442d97f7af2b",
      "tree": "fe9b04edbd06e17bf0d61c5b9706f21204fb68c1",
      "parents": [
        "fa9fdd1d5a59ffb8ed4cbe6338bfce7749625525"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 01:01:46 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 01:01:46 2026 -0400"
      },
      "message": "Remove dead workflow_data.proto and its orphaned SDK stubs (#670)\n\nworkflow_data.proto (ComponentStatus, WorkflowStatus, WorkflowModel, EdgeModel,\nPortModel, NodeModel) is imported by no other proto and referenced by no\nhand-written Java/Python/Go — a leftover workflow-engine model contract. Remove\nit and its three committed SDK stubs (workflow_data_pb2.py/.pyi/_grpc.py). Protos\nare glob-compiled, so the reactor regenerates cleanly without it."
    },
    {
      "commit": "fa9fdd1d5a59ffb8ed4cbe6338bfce7749625525",
      "tree": "fda3b8e38cd4d7a5455b4d38926af3b134c5bfb3",
      "parents": [
        "62c980a385065f7c999328ec5ca749188ecfe10d"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:59:04 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:59:04 2026 -0400"
      },
      "message": "Clean dead members from VirtualStreamProducer (#669)\n\nRemove the unused setInputStream/setOutputStream setters (0 callers; the streams\nare only ever set in the constructor and read via the getters), the dead local\n`ConcurrentLinkedQueue q` (the real buffer is the LinkedBlockingQueue `queue`),\nand the now-unused ConcurrentLinkedQueue import. The class stays — it is live\nvia its constructor and getters in DataStagingTask."
    },
    {
      "commit": "62c980a385065f7c999328ec5ca749188ecfe10d",
      "tree": "9e46215fc43e679c68628364fd3db8aa00f23ee4",
      "parents": [
        "dfb11c866d45ee0c8442a633f341b1f7a3ed0564"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:53:01 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:53:01 2026 -0400"
      },
      "message": "Remove dead commented-out orchestrator test stubs (#668)\n\nFour legacy test classes whose entire bodies are commented-out pre-Thrift-removal\ncode: BaseOrchestratorTest (empty class — its body is one big block comment) and\nits three empty subclasses NewOrchestratorTest, OrchestratorTestWithGRAM, and\nOrchestratorTestWithMyProxyAuth. They contain no @Test methods, nothing outside\nthe quartet references them, and test sources compile cleanly without them."
    },
    {
      "commit": "dfb11c866d45ee0c8442a633f341b1f7a3ed0564",
      "tree": "39e5a9b42d0808f63ac2fd3f7490a5714f04da66",
      "parents": [
        "a31da6edb27a090fc8b4f7f09bf509842cb54fba"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:50:24 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:50:24 2026 -0400"
      },
      "message": "Remove dead research-service methods (#667)\n\nThree unused public methods with zero callers across both repos:\n- AgentManagementService.terminateApplication(gatewayId, experimentId)\n- AiravataService.getUserProfile(authzToken, userId, gatewayId) — the 1-arg\n  getUserProfile(userId) is the live overload (used by ResearchResourceService)\n- AgentExperimentService.projectService() accessor — the projectService field\n  stays (read by getProjects); only the unused accessor is removed"
    },
    {
      "commit": "a31da6edb27a090fc8b4f7f09bf509842cb54fba",
      "tree": "295e3f6d214cdb3a70985bfc8d2cb724cb3b47dd",
      "parents": [
        "ce7dd9034ef353a446fe68515ebcbfe7933fef77"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:43:50 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:43:50 2026 -0400"
      },
      "message": "Remove dead ResearchProjectRepository query methods (#666)\n\nSix unused Spring Data declarations with zero callers: existsByOwnerId,\nfindProjectsByRepositoryResource, findProjectsByDatasetResourcesContaining,\nfindAllByOwnerId, findAllByOwnerIdOrderByCreatedAtDesc, and the malformed\nno-op State(StateEnum) (matches no Spring Data query prefix). The active\nstate-scoped variants (...AndState, findByIdAndState, findALlByState) are kept."
    },
    {
      "commit": "ce7dd9034ef353a446fe68515ebcbfe7933fef77",
      "tree": "1377e9ced4bd637b7b1c91e4c95e36b6409007ec",
      "parents": [
        "3d146be771ae42a6ac5d193be72fb602a515993e"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:38:56 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:38:56 2026 -0400"
      },
      "message": "Remove dead credential email-notification subsystem (#665)\n\nA fully self-contained, unreferenced cluster under credential-service/util:\nNotifierBootstrap, EmailNotifier, EmailNotifierConfiguration,\nEmailNotificationMessage, NotificationMessage, CredentialStoreNotifier, and\nEmailNotifierTest. The classes only reference each other and are reachable only\nfrom the dead NotifierBootstrap entry point; nothing wires them. The reactor\n(incl. test sources) compiles cleanly without them."
    },
    {
      "commit": "3d146be771ae42a6ac5d193be72fb602a515993e",
      "tree": "aba3448eeb0c039613d74a03765a08cfa792e5ed",
      "parents": [
        "5d122aab6820e323b5dbafd47097b98989be5f77"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:36:40 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:36:40 2026 -0400"
      },
      "message": "Remove dead iam util classes (#664)\n\nThree unreferenced legacy classes under iam-service/util: SharingModelConverter\n(unused proto-\u003eentity helper) and the Utils + JPAConstants pair (legacy JDBC-URL\nparsing helpers used only by each other). Zero references across both repos\n(the one wildcard import of iam.util.* does not use any of them); the reactor\ncompiles cleanly without them."
    },
    {
      "commit": "5d122aab6820e323b5dbafd47097b98989be5f77",
      "tree": "10de72593b91dfbaf4fdcc193999fe7743990be6",
      "parents": [
        "9a2987c8e0dc10fa143e090f6e18c2311570b43d"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:34:17 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:34:17 2026 -0400"
      },
      "message": "Remove dead orchestration util classes (#663)\n\nEight legacy classes under orchestration-service/util with zero references\nanywhere (verified across both repos including config/reflection-string usages;\nthe reactor compiles cleanly without them): OrchestratorServerConstants,\nProjectModelUtil, WorkflowContext, OrchestratorServerThreadPoolExecutor,\nAiravataJobState, PropertyResolver, ComputeRepositoryFactory, ExecutionType.\nLeftovers from the pre-DB-transactional orchestration engine."
    },
    {
      "commit": "9a2987c8e0dc10fa143e090f6e18c2311570b43d",
      "tree": "e54689e07a069e5e59f7ad01691b8b0943b056ed",
      "parents": [
        "ff893c851e477cc751b5b92a333cf77364d5400b"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 13 00:18:15 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 13 00:18:15 2026 -0400"
      },
      "message": "Fix SDK-launched experiment output listing and clone creation-time (#662)\n\nTwo experiment-data fixes surfaced via the portal:\n\n- \"No files\" for SDK-launched experiment output: the SDK persists an absolute\n  experiment_data_dir (\"/project/experiment\"). The staging write side\n  (DataStagingTask.buildDestinationFilePath) strips the leading \"/\" and anchors\n  the dir under the storage root, but resolve_user_storage_path honored it\n  as-is, so list_dir/dir_exists resolved against the SFTP chroot root (outside\n  the storage root) and listed nothing. Strip the leading \"/\" and anchor under\n  \"~/\", matching the write side and the bare-relative dirs the portal UI sets.\n\n- Clone shows creation time as \"56 years ago\" (epoch 0): the clone re-sends the\n  full experiment via update_experiment with creation_time cleared, but\n  saveExperiment only stamped creation_time on insert, so the update nulled the\n  column. Make creation_time set-once: on update, carry the stored value forward."
    },
    {
      "commit": "ff893c851e477cc751b5b92a333cf77364d5400b",
      "tree": "0aff12599683de33abaf753aa05c098829263094",
      "parents": [
        "8c7aa93878461d0a37449e9f1b2f9a6d7d35eb28"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Fri Jun 12 22:28:18 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 12 22:28:18 2026 -0400"
      },
      "message": "Externalize DB seeding, prune dead orchestration paths, fix job/experiment status (#661)\n\nDB seeding is moved out of the JVM lifecycle: the schema is seeded from\nexternal SQL (conf/db/seed.sql via MariaDB initdb) and airavata-server starts\nwith Hibernate ddl-auto\u003dvalidate, doing no programmatic DB modification beyond\nFlyway. Removed DBInitConfig/DBInitializer and every *DBInitConfig and\nDev*Initializer, and collapsed the V1+V2 migrations into a single baseline.\n\nRemoved dead infrastructure now that orchestration is DB-transactional: the\nKafka proxy (KafkaProxyService) and the legacy monitors (EmailBasedMonitor,\nRealtimeMonitor, ParsingTriggeringTask) plus their message (de)serializers.\n\nCommitted a fixed devstack SFTP keypair (conf/sftp/id_*) so fresh worktrees no\nlonger crash-loop the sftp container.\n\nFixes surfaced via the portal:\n- MonitoringTask persists job status under the job\u0027s owning (job-submission)\n  task id — JobPK is (jobId, taskId) and addJobStatus no-ops on a miss — and\n  records an ACTIVE transition so the Job Submission stage advances past QUEUED.\n- sacct polling uses --duplicates and picks the most-recently-submitted record,\n  so a reused slurm job id no longer reports a stale CANCELLED/COMPLETED state.\n- ExperimentSummaryEntity is a live @Subselect (no physical table to populate),\n  so the dashboard \"recent experiments\" search returns results.\n- ComputeMapper maps defaultCPUCount -\u003e defaultCpuCount (MapStruct acronym case)."
    },
    {
      "commit": "8c7aa93878461d0a37449e9f1b2f9a6d7d35eb28",
      "tree": "8aa82435ce5f06ce4a1edbae47d3c8532591dbbd",
      "parents": [
        "ff68e7b40468920a49874f9b95c619d29b801db2"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Fri Jun 12 13:43:15 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 12 13:43:15 2026 -0400"
      },
      "message": "feat(orchestration): SSH/SFTP×SLURM/AWS resource model on a DB-transactional executor (#660)\n\n* added quickstart and readme\n\n* explicit repeated-field proto mapping, SDK proto enum migration, and experiment persistence fixes\n\n* feat(orchestration): SSH/SFTP×SLURM/AWS resource model on a DB-transactional executor\n\nReplace the Helix/ZooKeeper/Curator/RabbitMQ orchestration stack with a\nDB-transactional ProcessExecutor that walks the PROCESS→TASK DAG using\nSELECT ... FOR UPDATE SKIP LOCKED, with the DB as the single source of truth.\n\n- Transport collapsed to fixed SSH (compute ops) + SFTP (data ops); endpoint read\n  off the compute/storage resource; ssh_port/sftp_port folded onto the resources\n- Provisioning modeled as ResourceType{SLURM,AWS} via ProvisioningAdapter\n- DbTask/DbTaskResult task SPI; remove the messaging/ (RabbitMQ) subsystem, Helix\n  files, and broker/ZooKeeper config + compose services (Kafka retained for the\n  remote-agent path)\n- docker-SLURM cluster added to the devstack; architecture docs (README/CLAUDE) updated"
    },
    {
      "commit": "ff68e7b40468920a49874f9b95c619d29b801db2",
      "tree": "9704992f3b8e0983766cd2ed00dff1c8134cfffb",
      "parents": [
        "87aaeee73325ecd99243bc09a192158e240b8b26"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Wed Jun 10 21:43:17 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 10 21:43:17 2026 -0400"
      },
      "message": "Proto-direct airavata-python-sdk + Keycloak self-service realm config (#659)\n\nRe-architects airavata-python-sdk into a proto-direct gRPC client. The resource helpers (research/compute/storage/iam/sharing/credential) return protobuf messages — or thin WithAccess/WithGroupAccess envelopes and composed pydantic models for cross-service shapes — instead of dict-transformed Thrift output, removing the legacy Thrift mapping layer and its enum-int tables in favor of proto-native types and strict typing, with deduplicated helpers aligned to the gRPC service breakdown and accompanying unit tests. Adds the public entry points the thin portal consumes directly (build_experiment, wrap_groups, list_application_deployments_for_module). Also enables Keycloak-owned account self-service in the dev realm seed (registration / password reset / remember-me) and registers the portal\u0027s local OIDC callback + post-logout URIs."
    },
    {
      "commit": "87aaeee73325ecd99243bc09a192158e240b8b26",
      "tree": "56df9652c5cd7d386c84f834ddfb8826d4a4dfca",
      "parents": [
        "7cadb49f1f4636583de90a93e97c5480c8e2f552"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 12:14:17 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 12:14:17 2026 -0400"
      },
      "message": "style: apply Spotless formatting to D4.3 storage/data-product files (#658)\n\nmvn spotless:apply reformatting for three files added/modified in the D4.3\nstorage work (DevStorageInitializer, DataProductInterface, UserStorageGrpcService)\nthat had minor line-wrapping violations the Spotless check now flags on every PR.\nFormatting-only; no behavior change."
    },
    {
      "commit": "7cadb49f1f4636583de90a93e97c5480c8e2f552",
      "tree": "f4b0d8cb7bf977448b585766deac0543a651b16a",
      "parents": [
        "c1be7bbb7a2fe5d8faf8b7cecabaf624e15d5210"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 12:12:41 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 12:12:41 2026 -0400"
      },
      "message": "feat(python-sdk): add framework-agnostic experiment-orchestration + queue-settings helpers (#657)\n\nRelocate API-side experiment behavior out of the Django portal SDK\n(airavata_django_portal_sdk) into the new gRPC SDK as a framework-agnostic\nairavata_sdk.helpers package. No Django/DRF/request/Thrift dependencies; every\nfunction takes an AiravataClient plus explicit kwargs and routes backend access\nthrough the gRPC facades (client.research / client.storage / client.sharing).\n\n- helpers/experiment_orchestration.py: launch, clone, is_input_file, and the\n  intermediate-output helpers (can_fetch_intermediate_output,\n  get_intermediate_output_process_status, fetch_intermediate_output,\n  get_intermediate_output_data_products). Repointed from\n  request.airavata_client.* + the Django user_storage module onto the gRPC\n  facades and proto snake_case field names. tmp input-file uploads are now moved\n  in place (move_file + update_replica_location) preserving the data-product\n  URI; clone-copy is implemented as download -\u003e upload -\u003e register_data_product\n  since the storage facade has no copy primitive.\n- helpers/queue_settings.py: the queue-settings calculator registry +\n  queue_settings_calculator decorator, relocated verbatim in behavior;\n  calculate_queue_settings now forwards *args/**kwargs so existing callers keep\n  working unchanged.\n\nsetuptools auto-discovers airavata_sdk.helpers via the existing airavata_sdk*\nglob; no version bump."
    },
    {
      "commit": "c1be7bbb7a2fe5d8faf8b7cecabaf624e15d5210",
      "tree": "9aa618159ca13be443ae06cfc4e4c5e9b1904c78",
      "parents": [
        "ac4c7e46c69bf9e20f41337a97179220b143da5d"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 02:59:41 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 02:59:41 2026 -0400"
      },
      "message": "perf(research-service): index DATA_REPLICA_LOCATION.FILE_PATH (#656)\n\nThe per-file data-product-uri resolution added for file listings looks up a data\nproduct by its replica file path (getDataProductByReplicaFilePath). Listing a\ndirectory resolves one such lookup per file, so without an index on FILE_PATH each\nwas a full scan of DATA_REPLICA_LOCATION — N scans for an N-file directory.\n\nAdd an index on FILE_PATH via @Index on DataReplicaLocationEntity (created by\nhbm2ddl on the running schema). Confirmed live: the lookup query\u0027s plan is now an\nindex ref seek (type\u003dref, key\u003dIDX_DATA_REPLICA_FILE_PATH, rows\u003d1) joining to\nDATA_PRODUCT by primary key, instead of a per-file table scan. Listing behavior\nunchanged (data_product_uri still stable/deduped). research-service tests: 53 pass."
    },
    {
      "commit": "ac4c7e46c69bf9e20f41337a97179220b143da5d",
      "tree": "7d02a59cf1876b8285c222baa4f15637f3a5f60d",
      "parents": [
        "2a034e79c83ec683bfe12f7e4886525f44d27615"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 02:42:07 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 02:42:07 2026 -0400"
      },
      "message": "fix(storage-service): move/symlink over SFTP instead of shell commands (#655)\n\nUserStorageService.moveFile and createSymlink ran \"mv\"/\"ln -s\" via\nadaptor.executeCommand, which the SFTP storage adaptor does not support, so\nboth failed with \"Command execution not supported on storage resources\" (the\nsame class of bug just fixed for deleteFile). Add moveFile (SFTP rename) and\ncreateSymlink (SFTP symlink) to the storage adaptor and call them.\n\nValidated live: moving a file relocates it (source gone, destination has the\ncontent); creating a symlink to a directory resolves through the link (listing\nthe link shows the target\u0027s contents). storage + compute unit tests pass."
    },
    {
      "commit": "2a034e79c83ec683bfe12f7e4886525f44d27615",
      "tree": "4fda474fa55be3856fe0efe8545a387a970c394c",
      "parents": [
        "e23618c9fc67bc18b9e18d5b65601ec08187dded"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 02:27:40 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 02:27:40 2026 -0400"
      },
      "message": "fix(storage-service): delete files over SFTP instead of shell rm (#654)\n\nUserStorageService.deleteFile ran \"rm -f \u003cpath\u003e\" via adaptor.executeCommand,\nbut the SFTP storage adaptor does not support command execution, so every file\ndelete failed with \"Command execution not supported on storage resources\".\nAdd a deleteFile to the storage adaptor (SFTP rm) and call it, mirroring how\ndeleteDir already uses deleteDirectory (SFTP rmdir).\n\nValidated live: uploading then deleting a file now succeeds (the file is gone)."
    },
    {
      "commit": "e23618c9fc67bc18b9e18d5b65601ec08187dded",
      "tree": "54bb917e6130794955d9398c282c6fc8adc02cd6",
      "parents": [
        "61112746588fd0319e229f3495aa63bbcf26c26f"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 02:12:19 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 02:12:19 2026 -0400"
      },
      "message": "feat(storage-service): surface per-file data-product URI in listings (#653)\n\nFile listings (list_dir / get_file_metadata / list_experiment_dir) now carry a\nstable data product URI per file, so clients can reference each stored file by\ndata product (downloads, deletes, selection) without a separate registry table.\n\n- DataProductInterface/DataProductRepository: getDataProductByReplicaFilePath\n  (JPQL join on the replica file path + gateway) finds the data product whose\n  gateway-data-store replica is a given path.\n- StorageProvider/StorageProviderImpl: getOrCreateDataProductByPath returns that\n  product\u0027s URI, registering a new FILE data product (single GATEWAY_DATA_STORE\n  replica) if none exists. This replaces the legacy file-path-to-data-product\n  mapping that the portal kept in its own ORM table.\n- UserStorageGrpcService populates FileMetadataResponse.data_product_uri for each\n  file (best-effort: directories and lookup failures yield an empty URI, never a\n  listing failure).\n\nValidated live: an uploaded file\u0027s get_file_metadata/list_dir return a\ndata_product_uri that is stable across calls (found, not re-registered) and\nresolves via the data-product service to the file\u0027s replica. storage-service +\nresearch-service tests pass."
    },
    {
      "commit": "61112746588fd0319e229f3495aa63bbcf26c26f",
      "tree": "2d1b1d98d2b8c2727b05d712140e42a6a99dcffd",
      "parents": [
        "c941eb2a4f7b2a61c3c6c8975038625662c743e0"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 01:57:52 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 01:57:52 2026 -0400"
      },
      "message": "feat(storage-service): expose file modified-time and content-type in metadata\n\nThe gRPC storage listing (list_dir/get_file_metadata) left modified_time and content_type unset even though FileMetadataResponse declares them. Populate both: FileMetadata gains modifiedTime + contentType; SSHJStorageAdaptor sets modifiedTime from SFTP stat mtime and guesses content_type from the filename; toFileMetadataResponse copies them through. created_time is not available over SFTP and stays unset."
    },
    {
      "commit": "c941eb2a4f7b2a61c3c6c8975038625662c743e0",
      "tree": "4d8fe05d4c4fe40ffbe4b7206b024bb3aa5800ec",
      "parents": [
        "f7ed91cf7145485dc7a4c8710112e966b9d0ae95"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 01:23:42 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 01:23:42 2026 -0400"
      },
      "message": "fix(research-service): correct data-product registration and replica round-trip\n\nFour proto-migration regressions in the data-product path: (1) an unset parent_product_uri defaults to \"\" (not null) under proto3, wrongly firing the parent-Collection check so no top-level product could register; (2) dataProductToModel called putAll on the proto builder\u0027s immutable map view (UnsupportedOperationException on every read) and dropped replicaLocations; (3) dataProductToEntity dropped replicaLocations so products persisted with no replica/file path; (4) replica ids were generated only when null, but empty-\"\" ids collided on the same PK so only one replica ever persisted. Hand-written default mappers (matching the existing appDeployment pattern) restore the full upload-\u003eregister-\u003eread round-trip; 53 research-service tests pass."
    },
    {
      "commit": "f7ed91cf7145485dc7a4c8710112e966b9d0ae95",
      "tree": "30673dfaffeccbe30d91e4814058d1fce271176a",
      "parents": [
        "d23df2882c6ea66492e15145be05d99cf0678d9d"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 00:21:29 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 00:21:29 2026 -0400"
      },
      "message": "fix: load storage data-movement interfaces via correct FK column\n\nStorageResourceEntity\u0027s @OneToMany joined on a RESOURCE_ID column the child entity never writes (it writes STORAGE_RESOURCE_ID, part of its composite @Id), so a storage resource never loaded its data-movement interfaces and the SFTP adaptor failed with \u0027No SCP data movement interface\u0027. Joins on STORAGE_RESOURCE_ID (read-only, child-owned). Also includes dev-storage seed/infra fixes (DevStorageInitializer host + self-heal; sftp volume chown)."
    },
    {
      "commit": "d23df2882c6ea66492e15145be05d99cf0678d9d",
      "tree": "b442b7418cfc6de6c278ec633d2f0806c90ac67c",
      "parents": [
        "18faafd8856d83ef8f99e589c9d2e82b0c5a4ce3"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Jun 09 00:21:27 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 00:21:27 2026 -0400"
      },
      "message": "fix(python-sdk): use product_uri in data-product facade requests\n\nresearch.get_data_product / get_parent_data_product / get_child_data_products built their request messages with a data_product_uri field, but the proto field is product_uri, so every call raised ValueError before reaching the server. Corrects the field name in all three (regression from #614)."
    },
    {
      "commit": "18faafd8856d83ef8f99e589c9d2e82b0c5a4ce3",
      "tree": "1951551560209939633178325a6c2b07fdf3a655",
      "parents": [
        "c5e5199c3ca2ace735abd5f973f0e2ed4777d0fd"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 23:30:33 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 23:30:33 2026 -0400"
      },
      "message": "refactor: nest the iam-service proto packages under api.iam (#648)\n\nRename the three non-iam_admin service protos in iam-service so all of iam-service\u0027s gRPC APIs share the org.apache.airavata.api.iam.* namespace: api.userprofile -\u003e api.iam.userprofile, api.sharing -\u003e api.iam.sharing, api.groupmanager -\u003e api.iam.groupmanager (iam_admin_service already lives at api.iam). A single flat api.iam is infeasible because sharing_service and group_manager_service share 17 message names, so the distinct services are nested as siblings under api.iam.\n\nThis is wire-breaking: the gRPC service paths change (e.g. /org.apache.airavata.api.sharing.SharingService/... -\u003e /org.apache.airavata.api.iam.sharing.SharingService/...). The in-repo Java consumers are updated (the iam Sharing/GroupManager gRPC handlers and the launcher\u0027s UserProfileGrpcService). compute-service\u0027s user_resource_profile_service.proto keeps api.userprofile and is unchanged - it coincidentally shared that Java package with iam\u0027s user_profile_service, so this rename actually un-splits the package across the two modules.\n\nThe Python SDK gRPC stubs for the three services are regenerated with the matching toolchain (protoc 6.31.1 / grpcio 1.80.0) so the diff is purely the rename; the .pyi stubs are unchanged. The full reactor builds green and the iam/compute tests pass. Regenerating the separate-repo portal client is a follow-up."
    },
    {
      "commit": "c5e5199c3ca2ace735abd5f973f0e2ed4777d0fd",
      "tree": "a864effdcc2f7cc4e40f1fc134b9ebdd31028631",
      "parents": [
        "89984b1e1a99994033308877191e2cd4320ce264"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 23:00:26 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 23:00:26 2026 -0400"
      },
      "message": "refactor: flatten the sharing packages into the iam namespace (#647)\n\nNow that the sharing code lives in iam-service, collapse its org.apache.airavata.sharing.{config,event,grpc,model,repository,service,util} Java packages into the matching org.apache.airavata.iam.* packages so the module has a single coherent namespace. This is an internal, server-side-only move: the proto packages (org.apache.airavata.api.sharing / .groupmanager) and the shared org.apache.airavata.sharing.registry.models.proto types are deliberately left untouched, and every external reference to sharing went through those proto/facade types, so no consumer import or gRPC/REST wire contract changes. The redundant SharingServiceConfig is removed because IamServiceConfig already component- and entity-scans org.apache.airavata.iam, which now covers the moved beans and entities. The one name clash — two different AbstractRepository base classes — is resolved by renaming the entity-direct sharing base to AbstractSharingRepository; it has a different type arity and a checked-exception contract than iam\u0027s model-converting AbstractRepository, so the two are kept distinct rather than force-merged. The full reactor builds green and iam-service tests (including the relocated ResourceSharingServiceTest) pass."
    },
    {
      "commit": "89984b1e1a99994033308877191e2cd4320ce264",
      "tree": "e9985889bf78df5eaeebbe7f9b70a813ae71c41a",
      "parents": [
        "200f94a83e04ba819cf05c742ba23f130020ee83"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:40:02 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:40:02 2026 -0400"
      },
      "message": "build(deps): bump github.com/pion/dtls/v3 in /airavata-agent (#646)\n\nBumps [github.com/pion/dtls/v3](https://github.com/pion/dtls) from 3.0.10 to 3.0.11.\n- [Release notes](https://github.com/pion/dtls/releases)\n- [Commits](https://github.com/pion/dtls/compare/v3.0.10...v3.0.11)\n\n---\nupdated-dependencies:\n- dependency-name: github.com/pion/dtls/v3\n  dependency-version: 3.0.11\n  dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "200f94a83e04ba819cf05c742ba23f130020ee83",
      "tree": "ece5ecd45eb43fcf05ce7b6dbedeeb468c7dfe39",
      "parents": [
        "588b40775a12d386986040a031ae509c1fa48f2f"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:39:51 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:39:51 2026 -0400"
      },
      "message": "build(deps): bump github.com/quic-go/quic-go in /airavata-agent (#621)\n\nBumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.55.0 to 0.59.1.\n- [Release notes](https://github.com/quic-go/quic-go/releases)\n- [Commits](https://github.com/quic-go/quic-go/compare/v0.55.0...v0.59.1)\n\n---\nupdated-dependencies:\n- dependency-name: github.com/quic-go/quic-go\n  dependency-version: 0.59.1\n  dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "588b40775a12d386986040a031ae509c1fa48f2f",
      "tree": "d9b4ba96231c4bd4fb86cb518bcbe6e1a4834835",
      "parents": [
        "4ba2624a6657670c181972e2c7adc6591cc89395"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:36:35 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:36:35 2026 -0400"
      },
      "message": "build(deps): bump github.com/fatedier/frp in /airavata-agent (#616)\n\nBumps [github.com/fatedier/frp](https://github.com/fatedier/frp) from 0.62.1 to 0.68.1.\n- [Release notes](https://github.com/fatedier/frp/releases)\n- [Changelog](https://github.com/fatedier/frp/blob/dev/Release.md)\n- [Commits](https://github.com/fatedier/frp/compare/v0.62.1...v0.68.1)\n\n---\nupdated-dependencies:\n- dependency-name: github.com/fatedier/frp\n  dependency-version: 0.68.1\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "4ba2624a6657670c181972e2c7adc6591cc89395",
      "tree": "6471598d0d2da8841aa602fa56590b56f838f606",
      "parents": [
        "4843e68ae43b626d5eb0ba5b21f8c3897b3a261e"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 22:36:16 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:36:16 2026 -0400"
      },
      "message": "refactor: merge sharing-service into iam-service (#645)\n\nFold the sharing-service module into iam-service so that identity (authentication, user/tenant profiles, gateways) and access control (permissions, groups, resource sharing) live in a single IAM module, eliminating the sharing -\u003e iam internal module dependency. This is a module-level merge only: all sources move under iam-service with their org.apache.airavata.sharing.* Java packages and org.apache.airavata.api.sharing / .groupmanager proto packages preserved, so every consumer import and the gRPC/REST wire contract are unchanged. The sharing-service module is dropped from the reactor, and research-service and airavata-server (both of which already depend on iam-service) have their now-redundant sharing-service dependency removed. The full reactor builds green and the relocated sharing tests pass."
    },
    {
      "commit": "4843e68ae43b626d5eb0ba5b21f8c3897b3a261e",
      "tree": "d03bb1ff881a42cb67923dd665abbb4369825576",
      "parents": [
        "ac72bac528d277c91e162b87d629195ea7362e98"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:33:35 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:33:35 2026 -0400"
      },
      "message": "build(deps): bump github.com/Azure/go-ntlmssp in /airavata-agent (#619)\n\nBumps [github.com/Azure/go-ntlmssp](https://github.com/Azure/go-ntlmssp) from 0.0.0-20221128193559-754e69321358 to 0.1.1.\n- [Release notes](https://github.com/Azure/go-ntlmssp/releases)\n- [Commits](https://github.com/Azure/go-ntlmssp/commits/v0.1.1)\n\n---\nupdated-dependencies:\n- dependency-name: github.com/Azure/go-ntlmssp\n  dependency-version: 0.1.1\n  dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "ac72bac528d277c91e162b87d629195ea7362e98",
      "tree": "5be707d62327e59743c9f6e8bfde66761a9446e6",
      "parents": [
        "c2b8c017b3ac691b465ad9b0bf29b002dda2b391"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:33:19 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:33:19 2026 -0400"
      },
      "message": "build(deps): bump org.bouncycastle:bcprov-jdk18on from 1.81 to 1.84 (#618)\n\nBumps [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) from 1.81 to 1.84.\n- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)\n- [Commits](https://github.com/bcgit/bc-java/commits)\n\n---\nupdated-dependencies:\n- dependency-name: org.bouncycastle:bcprov-jdk18on\n  dependency-version: \u00271.84\u0027\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "c2b8c017b3ac691b465ad9b0bf29b002dda2b391",
      "tree": "6cb380376ff526738e383ce0872292080a1235c0",
      "parents": [
        "8752c61ec61f710fc058a233359d3f4d2addb6e7"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:33:07 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:33:07 2026 -0400"
      },
      "message": "build(deps): bump org.bouncycastle:bcpkix-jdk18on from 1.81 to 1.84 (#617)\n\nBumps [org.bouncycastle:bcpkix-jdk18on](https://github.com/bcgit/bc-java) from 1.81 to 1.84.\n- [Changelog](https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html)\n- [Commits](https://github.com/bcgit/bc-java/commits)\n\n---\nupdated-dependencies:\n- dependency-name: org.bouncycastle:bcpkix-jdk18on\n  dependency-version: \u00271.84\u0027\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "8752c61ec61f710fc058a233359d3f4d2addb6e7",
      "tree": "f3ebb4eafa9f113729e2f0dd46e5f21c4139e473",
      "parents": [
        "ee6a15e0a614d1c470718c75017b8447b659ce80"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:32:25 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:32:25 2026 -0400"
      },
      "message": "build(deps): bump org.apache.kafka:kafka-clients from 3.9.1 to 3.9.2 (#615)\n\nBumps org.apache.kafka:kafka-clients from 3.9.1 to 3.9.2.\n\n---\nupdated-dependencies:\n- dependency-name: org.apache.kafka:kafka-clients\n  dependency-version: 3.9.2\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "ee6a15e0a614d1c470718c75017b8447b659ce80",
      "tree": "6753e06dd963cea345018720839b95e58bda502d",
      "parents": [
        "e0bb156566d1c5f2ac8e3b5217a3d37503f11b1e"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 07 22:32:11 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:32:11 2026 -0400"
      },
      "message": "build(deps): bump github.com/go-jose/go-jose/v4 in /airavata-agent (#613)\n\nBumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.1.3 to 4.1.4.\n- [Release notes](https://github.com/go-jose/go-jose/releases)\n- [Commits](https://github.com/go-jose/go-jose/compare/v4.1.3...v4.1.4)\n\n---\nupdated-dependencies:\n- dependency-name: github.com/go-jose/go-jose/v4\n  dependency-version: 4.1.4\n  dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "e0bb156566d1c5f2ac8e3b5217a3d37503f11b1e",
      "tree": "8a69cd0475a1f4200e908cffa76206e99923bdb6",
      "parents": [
        "0e3cef685d580f3b3f9ef22fc97123d68b248452"
      ],
      "author": {
        "name": "The Apache Software Foundation",
        "email": "root-asf-gitbox-commits@apache.org",
        "time": "Sun Jun 07 21:14:59 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:14:59 2026 -0400"
      },
      "message": "Set up default protection ruleset for default and release branches (#620)"
    },
    {
      "commit": "0e3cef685d580f3b3f9ef22fc97123d68b248452",
      "tree": "4ed683955b26a1609c8258ac3b2f9e81fc715b96",
      "parents": [
        "adb52410968b61f4a9c74486dda495ca13905b6f"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 22:05:08 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 22:05:08 2026 -0400"
      },
      "message": "ci: drop the JavaScript/TypeScript CodeQL analysis (#644)\n\nThe repository contains no JavaScript or TypeScript source, so the javascript-typescript CodeQL job has no code to scan and fails on every PR. Remove it from the language matrix, leaving actions, go, java-kotlin and python."
    },
    {
      "commit": "adb52410968b61f4a9c74486dda495ca13905b6f",
      "tree": "e83e75431cd8a1c69176fb74c44c6d8fee2934fe",
      "parents": [
        "d4e3bf340a65a9579b5e9350ec8b3b8cb785c8dd"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 21:57:46 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 21:57:46 2026 -0400"
      },
      "message": "refactor: move the research Resource catalog from sharing-service into research-service (#643)\n\nResourceEntity (table RESOURCE), TagEntity, ResourceStarEntity, their three repositories and the four research-only enums (ResourceTypeEnum/PrivacyEnum/StateEnum/StatusEnum) physically lived in sharing-service but were referenced only by research-service, which reached into sharing\u0027s internal model/repository packages 28 times. This is a package-only relocation (org.apache.airavata.sharing.{model,repository} -\u003e research.{model,repository}) with no schema change: the RESOURCE/TAG/RESOURCE_STAR tables and their Flyway migrations are untouched, and the broad @EntityScan over org.apache.airavata still discovers them. All consumers and the shared test persistence unit are repointed; research-service\u0027s sharing.model/repository imports drop from 28 to 0. Behavior-preserving; the reactor builds green and research-service\u0027s 53 tests pass."
    },
    {
      "commit": "d4e3bf340a65a9579b5e9350ec8b3b8cb785c8dd",
      "tree": "07a4d4cacef651fe48a36d280ecf69055c1c0f8c",
      "parents": [
        "bfa377caad50d22b3c5a2e4f7239809db08f1b3b"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 21:18:52 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 21:18:52 2026 -0400"
      },
      "message": "refactor: extract shared AuthTokenExtractor for the gRPC and HTTP auth paths (#642)\n\nGrpcAuthInterceptor and HttpAuthDecorator independently stripped the Bearer prefix, parsed the x-claims JSON header (each with its own ObjectMapper), and built the AuthzToken. A new AuthTokenExtractor (stripBearer / parseClaims / buildAuthzToken, with one shared ObjectMapper) provides those three steps; each transport keeps its own concerns: the gRPC UNAUTHENTICATED close, the HTTP UNAUTHORIZED return and per-header claims fallback, and the UserContext lifecycle. Behavior-preserving and the reactor builds green. The only airavata-server test failures are in the unrelated FileControllerTest, which fails identically on master."
    },
    {
      "commit": "bfa377caad50d22b3c5a2e4f7239809db08f1b3b",
      "tree": "9a4c3b953e39f11f8acb689c110bb6daf51981ba",
      "parents": [
        "abb331a9335fa0a4c1abbe3a397638d73433c265"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 21:18:20 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 21:18:20 2026 -0400"
      },
      "message": "fix: read the canonical kafka.broker.url key in KafkaProxyService (#641)\n\nKafkaProxyService injected ${airavata.kafka.broker-url}, a hyphenated key set only by the local Tilt/DinD compose file; real deployments (application.properties, ansible) define kafka.broker.url, so the proxy silently fell back to localhost:9092. Point the @Value at kafka.broker.url and drop the now-redundant -Dairavata.kafka.broker-url override from compose.yml."
    },
    {
      "commit": "abb331a9335fa0a4c1abbe3a397638d73433c265",
      "tree": "5ce96761836a0106c5097053f9f22aa712e02fc6",
      "parents": [
        "60808eccc6db8d371336c171399d8b36ab987f8c"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 20:32:32 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 20:32:32 2026 -0400"
      },
      "message": "refactor: collapse duplicated method families in research-service (#640)\n\nExperimentSummaryRepository.getAccessibleExperimentStatistics repeated six near-identical count-and-list-per-state blocks; they now drive a small table of (state list, count setter, list setter) records through one loop, with the \u0027all\u0027 row carrying a null state list (via Arrays.asList) that the underlying query already treats as \u0027no filter\u0027. ResearchHubService.stopSession and deleteSession, which differed only by a {remove:true} body, now delegate to a single deleteHubSession(sessionId, remove) helper that reuses one RestTemplate instance field instead of constructing one per call. Behavior-preserving; the reactor builds green and research-service\u0027s 53 tests, including ExperimentSummaryRepositoryTest, pass."
    },
    {
      "commit": "60808eccc6db8d371336c171399d8b36ab987f8c",
      "tree": "035f400112a3c8ed3c6c2d304a394c132feca112",
      "parents": [
        "b9baada5431c24cdc6920cf73e45c69f694df616"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 20:17:30 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 20:17:30 2026 -0400"
      },
      "message": "refactor: collapse duplicated method families in storage-service (#639)\n\nIn DataMovementRepository the four protocol getters were identical bar the mapper and the four adders bar the prefix/mapper; they now delegate to two private helpers (getMovement(id, mapper) and addMovement(entity)), with the per-protocol id injection kept in the typed wrappers and the asymmetric update* methods left untouched. In DataStagingTask the structurally identical getInput/getOutputStorageAdaptor methods now delegate to a single direction-parameterized helper, which also fixes the output method\u0027s log line that mislabeled the resource as \u0027input\u0027. Behavior-preserving; the reactor builds green and storage-service tests pass."
    },
    {
      "commit": "b9baada5431c24cdc6920cf73e45c69f694df616",
      "tree": "45877f41c00728eeaf99a69c0f2bc397a0403d4b",
      "parents": [
        "b0243ae2ec87144b2144c60bf86431aaad274898"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 20:06:01 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 20:06:01 2026 -0400"
      },
      "message": "docs: document the SLF4J placeholder logging convention in CLAUDE.md (#638)\n\nAdds a Logging section requiring parameterized {} placeholders over string concatenation in log statements, with the throwable passed as the trailing argument."
    },
    {
      "commit": "b0243ae2ec87144b2144c60bf86431aaad274898",
      "tree": "78a71d91612cb005a36e135c76cbb77d54a21d94",
      "parents": [
        "78ed5b8441fd9a99d8d0dfb39f1943b5a6aca937"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 20:05:27 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 20:05:27 2026 -0400"
      },
      "message": "refactor: collapse duplicated method families in CredentialStoreService (#637)\n\nThe three typed getters (SSH/Certificate/Password), the two SSH-summary-for-gateway methods, and the SSH/PWD delete methods each repeated the same fetch-check-log, collect, and delete-and-log scaffolding; they now delegate to three private helpers (getTypedCredential, collectSshSummaries with a Predicate\u003cSSHCredential\u003e, deleteCredential), whose log statements use SLF4J {} placeholders instead of string concatenation. Public/@Override signatures are preserved; two getter log lines reading \u0027credentialfor\u0027 are normalized to \u0027credential for\u0027 to match the thrown message. Behavior-preserving: the module\u0027s 36 tests, including CredentialStoreServiceTest\u0027s 14, pass unchanged."
    },
    {
      "commit": "78ed5b8441fd9a99d8d0dfb39f1943b5a6aca937",
      "tree": "9355b5c1f0f42ca678986f7178ef55ee8f28581f",
      "parents": [
        "9197d9a92e631a9f037088c25b53f72d561f968b"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 19:32:15 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 19:32:15 2026 -0400"
      },
      "message": "refactor: drop the redundant sharing-service SharingHelper (#636)\n\nResourceSharingService was the only consumer of sharing-service\u0027s util.SharingHelper, a near-duplicate of the shared org.apache.airavata.util.SharingHelper that was also incorrectly annotated @Service despite having a private constructor and only static methods. It now uses the core helper directly, since its arguments are compatible (registryHandler is a RegistryProvider, gatewayGroupsInitializer a GatewayGroupsProvider, and sharingHandler a SharingService which implements the SharingFacade the core method expects), so the duplicate file is removed. Behavior-preserving and the reactor builds green."
    },
    {
      "commit": "9197d9a92e631a9f037088c25b53f72d561f968b",
      "tree": "1d920f0510ae1e21b9962b9c2550fcfbed9d8996",
      "parents": [
        "36cff7403e2a47b7fa22ded3625000fb9241e6b1"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 19:26:17 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 19:26:17 2026 -0400"
      },
      "message": "refactor: dedup iam QueryConstants against the shared db.QueryConstants (#635)\n\nUserProfileRepository now static-imports its two JPQL query strings from the shared org.apache.airavata.db.QueryConstants (their definitions resolve to identical queries), so iam.util.QueryConstants drops the two duplicated user-profile queries plus four gateway queries that were already dead (GatewayRepository uses the core copies) and the five parameter constants only those queries referenced, leaving just the USER_ID/GATEWAY_ID keys it still needs. Behavior-preserving and the reactor builds green."
    },
    {
      "commit": "36cff7403e2a47b7fa22ded3625000fb9241e6b1",
      "tree": "8d84e7d20435cc0203d4da85a18b490d946a7a4d",
      "parents": [
        "20aea9112ab7d7fac3d5c11dee8fcdc437b3b82e"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 19:12:00 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 19:12:00 2026 -0400"
      },
      "message": "refactor: move JsonMapConverter into the shared db package (#634)\n\nThe compute-service and storage-service each carried a byte-identical copy of this JPA JSON-map AttributeConverter; this keeps a single copy in org.apache.airavata.db alongside JsonListConverter and points the two @Convert references (ComputeJobSubmissionEntity, StorageDataMovementEntity) at it. Behavior-preserving and the reactor builds green."
    },
    {
      "commit": "20aea9112ab7d7fac3d5c11dee8fcdc437b3b82e",
      "tree": "a9c1c0fabfc56cfcac5d4d84748aec679449a155",
      "parents": [
        "59c4a0523fd0ce123759368f8d90e4ce49e75904"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 18:45:47 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 18:45:47 2026 -0400"
      },
      "message": "build: consolidate the Testcontainers Ryuk-disable flag into root surefire (#633)\n\nTESTCONTAINERS_RYUK_DISABLED\u003dtrue was repeated in four module surefire blocks (airavata-api, iam, compute, orchestration); this hoists it into the root maven-surefire-plugin configuration so it applies to every module\u0027s tests via inheritance and removes the three RYUK-only blocks plus airavata-api\u0027s copy. Verified with help:effective-pom that the flag still reaches iam/compute/orchestration and now also the other Testcontainers modules, and the reactor builds green."
    },
    {
      "commit": "59c4a0523fd0ce123759368f8d90e4ce49e75904",
      "tree": "5c8fae1f4609cbc5bcb1f2acf94420175bbe0181",
      "parents": [
        "69b5cf15514814a3cdc26375d676eac845f3b111"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 18:35:17 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 18:35:17 2026 -0400"
      },
      "message": "build: centralize dependency versions and drop redundant config (#632)\n\nHoists the Mockito (5.23.0) and MapStruct (now a mapstruct.version property) versions into the root pom so the modules stop repeating them — which also aligns airavata-server\u0027s test Mockito (previously 5.17.0 from the Spring Boot BOM) with the rest — removes the four spring-boot-starter version pins and the misplaced spring-boot-maven-plugin entry from dependencyManagement (all already supplied by the imported spring-boot-dependencies BOM), and bumps the spring-boot-maven-plugin pluginManagement pin to 3.5.12 to match. Behavior-preserving; the reactor builds green and dependency:tree confirms versions are unchanged apart from the intended Mockito alignment."
    },
    {
      "commit": "69b5cf15514814a3cdc26375d676eac845f3b111",
      "tree": "c009082153b9bd64e4cf3de882f10c3a13693b79",
      "parents": [
        "3a052096fadb0a96c5f1303ffc5acf338dca8219"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 17:24:01 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 17:24:01 2026 -0400"
      },
      "message": "Remove airavata-jupyterhub (moved to apache/airavata-portals) (#631)\n\nThe JupyterHub deployment directory has no Maven or build coupling to the middleware and belongs with the gateway-facing portals; it has been moved to apache/airavata-portals, so this removes it here along with its CLAUDE.md section and the stale .dockerignore comment."
    },
    {
      "commit": "3a052096fadb0a96c5f1303ffc5acf338dca8219",
      "tree": "0fc5ab7b98b7365168478dc7349f5bdb584af7b1",
      "parents": [
        "22b59bd5f6cdc966f15779cfb5127955aacecd14"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 17:16:02 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 17:16:02 2026 -0400"
      },
      "message": "style: fix Spotless formatting violations on master (#630)\n\nmvn spotless:check has been failing on master and therefore on every open PR; this applies mvn spotless:apply to the six offending files (SSHJStorageAdaptor, DevStorageInitializer, ExpCatalogDBInitConfig, SharingService, UserStorageGrpcService, StorageMapper) to re-wrap lines, normalize import grouping and drop unused imports. Formatting-only, no behavior change, and the reactor still builds."
    },
    {
      "commit": "22b59bd5f6cdc966f15779cfb5127955aacecd14",
      "tree": "2d010fcdff42deb78a2ee72fd7822d86e601f309",
      "parents": [
        "bb09012c61ffc686a9f7ac851ed33370e82e57c1"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 17:04:59 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 17:04:59 2026 -0400"
      },
      "message": "Remove more dead code from airavata-api (#629)\n\n* chore: remove dead URL/HTML helper methods from StringUtil\n\ngetURLS, createHTMLUrlTaggedString and createHTMLUrlTaggedString2 generate portal-presentation markup, have no callers, and were the only users of the regex imports, so they and the now-unused Matcher/Pattern imports are removed.\n\n* chore: drop unused cross-domain mapper declarations from ExecutionMapper\n\nThe queueStatus and gateway toModel/toEntity methods have no callers (those conversions live in compute\u0027s ComputeMapper and iam\u0027s GatewayEntityMapper), are never used as MapStruct sub-mappers, and only pulled in four cross-module imports, so all are removed.\n\n* chore: remove unused AgentExecution entities, repositories and empty AgentMapper\n\nAgentExecutionEntity/AgentExecutionStatusEntity, their repositories and the empty AgentMapper are never read or written, so they are removed along with their two now-orphaned entries in the shared test persistence unit (which still bootstraps cleanly).\n\n* chore: remove stubbed Utility methods and SSHUtil.main\n\nUtility.encrypt always returned null and loadKeyStore/getPassword were unused (credential encryption is handled by CredentialEncryptionUtil), and SSHUtil.main was a manual test harness, so they and their now-unused imports are removed while the live generateKeyPair/validate/execute paths are kept."
    },
    {
      "commit": "bb09012c61ffc686a9f7ac851ed33370e82e57c1",
      "tree": "087bfec04ba596b007d316fdcea167ab7756b05d",
      "parents": [
        "6a0ca453d0317213b9c1e6d47d6f46b192742faa"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 16:46:56 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 16:46:56 2026 -0400"
      },
      "message": "Remove dead code from airavata-api (#628)\n\n* chore: remove dead instrumentation classes StatCounter/CountWriterTask/LatencyWriterTask\n\nThese three messaging/util classes reference only each other and have no\nexternal callers; StatCounter also spun up two Timer threads writing to\nhardcoded /tmp paths. Remove the whole unused cluster.\n\n* chore: delete unused SwingUtil AWT/Swing helper\n\nA desktop GUI helper has no place in a headless gRPC/REST server and has\nzero references.\n\n* chore: remove unwired MonitoringServer and its ServiceRegistry/ServiceStatus\n\nMonitoringServer stands up a com.sun HttpServer that is never constructed or\nregistered; metrics are served by Spring Actuator. The three classes\nreference only each other. GaugeMonitor/CountMonitor are untouched.\n\n* chore: delete unused LocalEventPublisher\n\nAn unwired Guava EventBus wrapper with no Spring stereotype and no callers;\nthe real publishers are RabbitMQ-backed.\n\n* chore: remove dead SSH-adaptor cluster from compute-service\n\nSshAgentAdaptor, StorageResourceAdaptorImpl, SshAdaptorParams and\nAdaptorParams form a closed, unreachable cluster; the live factory wires\nSSHJ adaptors exclusively. The StorageResourceAdaptor interface,\nStandardOutReader and SSHConnectionService are kept.\n\n* chore: delete unused appcatalog proto-builder helpers from compute-service\n\nAppInterfaceUtil and AppDeploymentUtil build research-service appcatalog\nprotos and have no callers."
    },
    {
      "commit": "6a0ca453d0317213b9c1e6d47d6f46b192742faa",
      "tree": "1158c91037d1ba7300c594568f3f7e5264ee2cd3",
      "parents": [
        "e9db41f83054941a69dc6bcc993fa8b5e860360b"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sun Jun 07 16:37:05 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 07 16:37:05 2026 -0400"
      },
      "message": "Remove leftover Apache Thrift naming (#627)\n\n* refactor: rename ThriftUtils to SubTaskModelDecoder and move to task package\n\nThe class is a pure protobuf sub-task decoder with no Thrift content; the\nname was a leftover from the pre-gRPC era. Relocate it next to its only\nconsumers in the task package and update both call sites.\n\n* refactor: rename ThriftDataModelConversion to SharingModelConverter\n\nThe class only converts proto UserProfile to a sharing UserEntity; there is\nno Thrift involved. Rename to reflect what it does.\n\n* refactor: rename toThrift* converters to to*Entity in SharingGrpcService\n\nThe six private converters produce JPA *Entity types, not Thrift objects.\nRename them (and drop the Thrift-related comments) for accuracy.\n\n* chore: remove stale Thrift references from comments and parameter names\n\nDe-Thrift leftover javadoc, the AbstractRepository constructor parameter\n(thriftGenericClass -\u003e modelClass), an SSHAccountManager parameter, and four\nexception-class comments. No behavior change.\n\n* chore: remove Thrift references from proto comments\n\nComment-only edits in three protos; wire format and message identity are\nunchanged."
    },
    {
      "commit": "e9db41f83054941a69dc6bcc993fa8b5e860360b",
      "tree": "37927dc8c81be67003ac968ebf3ac055ff80c85f",
      "parents": [
        "6f0bca0796aeb08817ad106ef061dd2df5238e78"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 06 14:11:14 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 06 14:11:14 2026 -0400"
      },
      "message": "chore: reword duplicate-seed WARNs and quiet Kafka config dumps (#626)\n\nReword the idempotent-seed warnings (\"A domain with id\u003d... already exists,\nskipping recreation\") and raise the Kafka client *Config loggers to WARN so\ntheir verbose value dumps stay out of normal INFO logs (recoverable by\nsetting those loggers back to INFO)."
    },
    {
      "commit": "6f0bca0796aeb08817ad106ef061dd2df5238e78",
      "tree": "d66d7fc34e3b28d5781888f60179eace66911c88",
      "parents": [
        "bcd675749df95b3e319beb8d8350744a06b71d66"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 06 12:47:41 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 06 12:47:41 2026 -0400"
      },
      "message": "fix: seed default sharing data idempotently without ERROR noise (#625)\n\nOn every server restart against an existing DB, default-data seeding re-ran\nand SharingService.create{Domain,EntityType,PermissionType} logged the\nexpected duplicate at ERROR with a full stack trace. Make those creates\nidempotent: on an existing entry, log one clean WARN and return the existing\nid instead of throwing/wrapping. The seeder logs \"Ensured\" and surfaces\ngenuine failures at ERROR."
    },
    {
      "commit": "bcd675749df95b3e319beb8d8350744a06b71d66",
      "tree": "245efd5a087f171452222ab3f2ed2a2d2500d25a",
      "parents": [
        "a5829a069dab899dc6a56688f64715575bd9eb45"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 06 02:19:08 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 06 02:19:08 2026 -0400"
      },
      "message": "fix: eliminate server cold-start startup warnings (#624)\n\nAlign the SHARING composite-key column lengths in SharingEntity/SharingPK\nwith the V1 baseline (varchar(152)) so Hibernate ddl-auto stops trying to\nwiden them past InnoDB\u0027s 3072-byte key limit. Register Armeria\u0027s\nBeanPostProcessor as a static @Bean (excluding the library\u0027s non-static\nArmeriaBeanPostProcessorConfiguration) to remove the BPP-eligibility warning.\nThe server now cold-starts with zero WARN/ERROR."
    },
    {
      "commit": "a5829a069dab899dc6a56688f64715575bd9eb45",
      "tree": "40e7ff31415aaace63eb79afcea42087e57c8f15",
      "parents": [
        "9403d8768290659cdbd103de8bd46a376bc14d93"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 06 01:46:27 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 06 01:46:27 2026 -0400"
      },
      "message": "dev: fix DevStorage cold-start init in the containerized server (#623)\n\nMount conf/ into the server so it finds the dev SFTP keypair and the\ncredential-store keystore, and run DevStorageInitializer on\nApplicationReadyEvent so the default gateway exists before its storage\npreference is added."
    },
    {
      "commit": "9403d8768290659cdbd103de8bd46a376bc14d93",
      "tree": "5767d4fcb86c2aaeaa9464a2d9d271baf2be30c5",
      "parents": [
        "0cb57acc8b3fc232c07526ba191735ecf99e05c2"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Jun 06 00:55:50 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 06 00:55:50 2026 -0400"
      },
      "message": "dev: single-container Docker-in-Docker Tilt environment with HTTPS ingress (#622)\n\nRuns the full dev stack (infra + server) inside one host-visible DinD\ncontainer with its own Docker daemon + registry, driven entirely by\n`tilt up`/`tilt down`. Traefik serves *.airavata.localhost over HTTP and\nHTTPS (mkcert). Server connection settings are injected via\nJAVA_TOOL_OPTIONS; /actuator/health is restored (Armeria actuator bridge)\nand InfrastructureHealthIndicator reads broker hosts from config instead\nof hardcoded localhost."
    },
    {
      "commit": "0cb57acc8b3fc232c07526ba191735ecf99e05c2",
      "tree": "37b644cf8aee12996ba75cee59cc312b1dcfe5c0",
      "parents": [
        "82506ff512fa13290df1d5314fae765303a28d17"
      ],
      "author": {
        "name": "yasithdev",
        "email": "yasith.j@icloud.com",
        "time": "Sun Apr 12 00:22:15 2026 -0500"
      },
      "committer": {
        "name": "yasithdev",
        "email": "yasith.j@icloud.com",
        "time": "Sun Apr 12 00:22:15 2026 -0500"
      },
      "message": "add CLAUDE.md\n"
    },
    {
      "commit": "82506ff512fa13290df1d5314fae765303a28d17",
      "tree": "e603941c58bf4e4e75314a45e1c027e3ff128c6f",
      "parents": [
        "f250f6dde8e5f37eb857b5bf3117b556ee2e4b90"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Sat Apr 11 23:12:07 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Apr 11 23:12:07 2026 -0500"
      },
      "message": "fix: sharing init, storage mapping, SDK facades, and dev infra (#614)\n\n* feat: airavata server fixes, SDK facades, auto-generated SFTP keys\n\n- Fix sharing EntityRepository null-safe casting\n- Fix ResearchMapper projectId/projectID mapping\n- Update credential store encryption and key generation\n- SDK facade clients updated for gRPC service alignment\n- Tiltfile auto-generates SSH keypair for SFTP container (no static keys in repo)\n- DevStorageInitializer reads keypair from conf/sftp/ instead of generating\n- Keycloak custom theme for dev login\n- Gitignore conf/sftp/id_* generated keys\n\n* fix: use proc check instead of ss for SFTP healthcheck (ss not available in image)\n\n* fix: map DataMovementInterfaceEntity to STORAGE_INTERFACE table instead of DATA_MOVEMENT_INTERFACE"
    },
    {
      "commit": "f250f6dde8e5f37eb857b5bf3117b556ee2e4b90",
      "tree": "4625315f662f78d56a75426e9ecb4ecea82d3cbe",
      "parents": [
        "976c07d494769deb3da3a1d27516f54528029d0e"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Thu Apr 09 21:56:16 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 09 21:56:16 2026 -0500"
      },
      "message": "refactor: gRPC/Armeria migration with full module boundary enforcement (#612)\n\nComplete modernization of Airavata\u0027s service architecture. Server starts\nand serves gRPC + REST on port 9090. All tests pass.\n\nCo-authored-by: Claude Opus 4.6 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "976c07d494769deb3da3a1d27516f54528029d0e",
      "tree": "41ac94401cb44dd096ecc055262a701a8281e98c",
      "parents": [
        "ed2986f79151f06d8ae0a4dc896c63f8a849468c"
      ],
      "author": {
        "name": "yasithdev",
        "email": "yasith.j@icloud.com",
        "time": "Tue Mar 31 02:29:48 2026 -0400"
      },
      "committer": {
        "name": "yasithdev",
        "email": "yasith.j@icloud.com",
        "time": "Tue Mar 31 02:29:48 2026 -0400"
      },
      "message": "chore: add .worktrees/ to gitignore\n"
    },
    {
      "commit": "ed2986f79151f06d8ae0a4dc896c63f8a849468c",
      "tree": "ed4c699b5a6a0c8bf54a97cd87c820e49a83b7a9",
      "parents": [
        "c933b76efe7ae44c1cf9fe2e4de81ede963b84d0"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Tue Mar 31 00:58:26 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Mar 31 00:58:26 2026 -0400"
      },
      "message": "security: upgrade credential encryption from AES/CBC to AES/GCM (#610)\n\n* security: upgrade credential encryption from AES/CBC to AES/GCM\n\nReplace AES/CBC/PKCS5Padding with AES/GCM/NoPadding for credential\nstore encryption. The old code used a static zero IV which is insecure.\nGCM provides authenticated encryption with random IVs prepended to\nthe ciphertext.\n\nExtracted from #556.\n\n* security: add legacy AES/CBC fallback for transparent migration\n\nOn decrypt, try GCM first. If the auth tag fails (AEADBadTagException),\nfall back to the old AES/CBC/PKCS5Padding with static zero IV. This\nallows existing credentials to be read without re-encryption.\n\nCredentials will migrate to GCM format on next update/rotation —\nwrites always use AES/GCM.\n\n* test: add unit tests for GCM/CBC encryption and legacy fallback\n\n- testFallbackDecryptsLegacyCBC: CBC-encrypted data decrypted via fallback\n- testFallbackDecryptsNewGCM: GCM-encrypted data decrypted via fallback\n- testGcmDecryptRejectsLegacyData: GCM decrypt throws on CBC data\n\n* security: remove fallback, add migration script instead\n\nReplace transparent fallback with a one-time migration script\n(MigrateCredentialEncryption) that re-encrypts all CREDENTIALS rows\nfrom legacy AES/CBC to AES/GCM. Run before deploying the GCM-only code.\n\nUsage:\n  java MigrateCredentialEncryption \u003cjdbcUrl\u003e \u003cdbUser\u003e \u003cdbPass\u003e \\\n    \u003ckeystorePath\u003e \u003ckeyAlias\u003e \u003ckeystorePass\u003e\n\nThe script skips rows already in GCM format.\n\n* style: spotless:apply on MigrateCredentialEncryption\n\n* Potential fix for code scanning alert no. 129: Use of a broken or risky cryptographic algorithm\n\nCo-authored-by: Copilot Autofix powered by AI \u003c62310815+github-advanced-security[bot]@users.noreply.github.com\u003e\n\n* fix: make decryptLegacy public for cross-package access from migration script\n\n---------\n\nCo-authored-by: Copilot Autofix powered by AI \u003c62310815+github-advanced-security[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "c933b76efe7ae44c1cf9fe2e4de81ede963b84d0",
      "tree": "dbe80037d1e9dd01f377cfe313c9238e57e84b1e",
      "parents": [
        "4c545fbb6adef8209de9c9a5e9cebbc338ad9fe3"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Mar 30 16:21:25 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 16:21:25 2026 -0400"
      },
      "message": "feat: add root Makefile for common build/serve targets (#611)\n\nExtracted from #556. Provides convenience targets:\n- make build: full Maven build (skip tests)\n- make serve: build + run fat JAR\n- make compile: fast compile only\n- make serve-dev: compile + spring-boot:run (hot reload)\n- make test: run test suite"
    },
    {
      "commit": "4c545fbb6adef8209de9c9a5e9cebbc338ad9fe3",
      "tree": "de1803bb94a4d25a065c9d929b241dea482645f9",
      "parents": [
        "c42a928c3848fdd3648345a4a24fa0eecdadedd4"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Mar 30 15:28:13 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:28:13 2026 -0400"
      },
      "message": "deps: bump grpc-go from 1.64.1 to 1.79.3 in airavata-agent (#605)\n\nIncludes security fix for authorization bypass via malformed :path headers. Also bumps protobuf to 1.36.10 and transitive deps."
    },
    {
      "commit": "c42a928c3848fdd3648345a4a24fa0eecdadedd4",
      "tree": "b0ee2a08711eb530b71ee731a4a65a88cdca714a",
      "parents": [
        "d4110da58f226b24e3fc4d4f61ce9bd8637c5b55"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Mar 30 15:27:14 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:27:14 2026 -0400"
      },
      "message": "deps: bump shiro-core from 2.0.4 to 2.1.0 (#588)\n\nBumps [org.apache.shiro:shiro-core](https://github.com/apache/shiro) from 2.0.4 to 2.1.0.\n- [Release notes](https://github.com/apache/shiro/releases)\n- [Changelog](https://github.com/apache/shiro/blob/main/RELEASE-NOTES)\n- [Commits](https://github.com/apache/shiro/compare/shiro-root-2.0.4...shiro-root-2.1.0)\n\n---\nupdated-dependencies:\n- dependency-name: org.apache.shiro:shiro-core\n  dependency-version: 2.1.0\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "d4110da58f226b24e3fc4d4f61ce9bd8637c5b55",
      "tree": "9fb546c2ad7b93593d75893e16319c94c2014ce5",
      "parents": [
        "2ef5e00a71b0b5747814089a3fa0dcacbff92c0f"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Mar 30 15:27:01 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:27:01 2026 -0400"
      },
      "message": "deps: align all spring-boot artifacts to 3.5.12 (#609)\n\nFollow-up to #604. Aligns spring-boot-starter-web,\nspring-boot-starter-data-jpa, spring-boot-maven-plugin, and\nspring-boot-dependencies BOM to 3.5.12. All tests pass."
    },
    {
      "commit": "2ef5e00a71b0b5747814089a3fa0dcacbff92c0f",
      "tree": "f3cce1e813a98c772c8d4713c54df7a2d46a3ac3",
      "parents": [
        "6eda0b8fc238201ada7884646589a391fa8f56d1"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Mar 30 15:25:10 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:25:10 2026 -0400"
      },
      "message": "deps: bump spring-boot-starter-actuator from 3.5.3 to 3.5.12 (#604)\n\nFollow-up commit will align spring-boot-starter-web and spring-boot-starter-data-jpa to 3.5.12."
    },
    {
      "commit": "6eda0b8fc238201ada7884646589a391fa8f56d1",
      "tree": "626288753ab2112025d3fb543bba3b91fa6f5b1b",
      "parents": [
        "4009f1e04e924515bb2ff661a200f2e047dd01a5"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Mar 30 15:25:04 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:25:04 2026 -0400"
      },
      "message": "deps: align jackson siblings after #590 (#608)\n\njackson-databind 2.19.1 → 2.21.1, jackson-annotations 2.19.1 → 2.19.0 (latest available). All tests pass."
    },
    {
      "commit": "4009f1e04e924515bb2ff661a200f2e047dd01a5",
      "tree": "d22f04414ad171c0c1d3636320f4da8f96c8cb42",
      "parents": [
        "0142fea17a51100ddf9049b4fbd5af3994c7fe02"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Mar 30 15:21:02 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:21:02 2026 -0400"
      },
      "message": "deps: bump jackson-core from 2.19.1 to 2.21.1 (#590)\n\nFollow-up commit will align jackson-databind and jackson-annotations to 2.21.1."
    },
    {
      "commit": "0142fea17a51100ddf9049b4fbd5af3994c7fe02",
      "tree": "3c502adf6f573852b0c616580bb11e0ea8f4d0c9",
      "parents": [
        "49d74eac9d16602b0f1b22ec0edf97ee2c13f5cf"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Mar 30 15:20:19 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:20:19 2026 -0400"
      },
      "message": "deps: bump zookeeper from 3.9.4 to 3.9.5 (#591)\n\nBumps org.apache.zookeeper:zookeeper from 3.9.4 to 3.9.5.\n\n---\nupdated-dependencies:\n- dependency-name: org.apache.zookeeper:zookeeper\n  dependency-version: 3.9.5\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "49d74eac9d16602b0f1b22ec0edf97ee2c13f5cf",
      "tree": "c1467ff44191b721ae957afcdc5e880af44963a3",
      "parents": [
        "47e821e0cfa92d2852837485a98676f62101ee7c"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Mar 30 15:13:26 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:13:26 2026 -0400"
      },
      "message": "deps: align all log4j artifacts to 2.25.3 (#607)\n\nFollow-up to #587 — bump log4j-api, log4j-slf4j2-impl, log4j-1.2-api from 2.24.0 to 2.25.3. All 9 modules build, all tests pass."
    },
    {
      "commit": "47e821e0cfa92d2852837485a98676f62101ee7c",
      "tree": "4b69f17581c565421f9e1684edf30b924b0e470d",
      "parents": [
        "dbb1ec5756e4adbaa86c740f3594ef5a8d2afa74"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Mar 30 15:06:19 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 15:06:19 2026 -0400"
      },
      "message": "deps: bump log4j-core from 2.24.0 to 2.25.3 (#587)\n\nDependabot version bump. Follow-up commit will align log4j-api, log4j-slf4j2-impl, and log4j-1.2-api to 2.25.3."
    },
    {
      "commit": "dbb1ec5756e4adbaa86c740f3594ef5a8d2afa74",
      "tree": "ebd21ef26182bd22e1d33929bd1c200dab1d5247",
      "parents": [
        "f45854ae85ce48803d4164e29e284342d346d484"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Mar 30 14:23:37 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 14:23:37 2026 -0400"
      },
      "message": "reliability: consolidate monitoring, migrate JDBC, fix JPA, harden startup/shutdown (#603)\n\nConsolidate 4 redundant MonitoringServer instances into unified :9097. Bridge Spring datasource into legacy JDBC config (single source of truth). Switch to Spring Boot auto-configured JPA with @EntityScan + PhysicalNamingStrategyStandardImpl. Replace wurstmeister/kafka with apache/kafka:3.9.0 (KRaft). Add compose healthchecks, graceful shutdown, HikariCP resilience, infrastructure health indicator."
    },
    {
      "commit": "f45854ae85ce48803d4164e29e284342d346d484",
      "tree": "58d3b9a4afa1973f9e677f7f2b77dceb539790b6",
      "parents": [
        "b41fbfa93ff224144a7eeae55f051e06d28a7277"
      ],
      "author": {
        "name": "Yasith Jayawardana",
        "email": "yasith@gatech.edu",
        "time": "Mon Mar 30 11:41:29 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Mar 30 11:41:29 2026 -0400"
      },
      "message": "cleanup: lean core — remove dead code, fix cold-start, align docs (#602)\n\nPost-server-collapse cleanup: remove dead dev-tools (PHP SDK, amqpwstunnel, simstream, job-status-rest-server), promote airavata-python-sdk to top level, consolidate load-client as Python, delete airavata-fuse, clean examples, remove @Deprecated code, triage TODOs/FIXMEs, prune Maven deps, fix unified server cold-start (fat JAR, actuator, Hibernate 6.6 compatibility, config consolidation), update all docs/scripts/Dockerfile/Ansible for unified architecture, sync properties.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) \u003cnoreply@anthropic.com\u003e"
    }
  ],
  "next": "b41fbfa93ff224144a7eeae55f051e06d28a7277"
}
