)]}'
{
  "commit": "6b99ae83b37d5fc599fb367c37b47d87ce602aa2",
  "tree": "2e19fa69c07cf87eb7e7d9c9a3f25db00c5a8546",
  "parents": [
    "579fddbfc1953169812e8c66d605417bbfe204e5"
  ],
  "author": {
    "name": "Michele Sciabarra",
    "email": "30654959+sciabarracom@users.noreply.github.com",
    "time": "Sat Aug 29 17:23:18 2026 +0200"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Sat Aug 29 17:23:18 2026 +0200"
  },
  "message": "fix: validate database and bucket names in user provisioning (#121)\n\nFollow-up to #109, which validated spec.namespace but left two other\ntenant controlled WhiskUser fields flowing unsanitized into shell\ncommands executed inside the data pods via kubectl exec.\n\n* spec.postgres.database reached `bash -c \"... psql --dbname {db_name}\"`\n  in exec_psql_command_in_db. Unlike the namespace field it never\n  becomes a filename, so it was not even constrained to path safe\n  characters.\n* spec.object-storage.{data,route}.bucket reached\n  `sh -c \"echo \u0027{command}\u0027 | weed shell\"` in the seaweedfs client,\n  where a quote breaks out of the single quoted string.\n\nAdds util.validate_database_name and util.validate_bucket_name next to\nthe existing validate_namespace and applies them at the call sites and\nat the shell sinks, plus matching CEL rules on the CRD so the API server\nrejects the payload before the operator sees it. The regexes and the CEL\nrules were cross checked to accept exactly the same inputs.\n\nAlso:\n* guards the latent render_kvrocks_script / exec_kvrocks_command pair,\n  which repeats the same pattern but is not currently wired into the\n  user path\n* makes validate_namespace return False for non string input instead of\n  raising TypeError\n* corrects a copy pasted error message referring to exec_mongosh_command\n  inside exec_psql_command\n\nCo-authored-by: Claude Opus 5 (1M context) \u003cnoreply@anthropic.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "878805f71e79923c12a577655684eb2fc4487485",
      "old_mode": 33188,
      "old_path": "deploy/nuvolaris-permissions/whisk-user-crd.yaml",
      "new_id": "9a70ecade66eb567c9d4a271fa58f4c10bb732a8",
      "new_mode": 33188,
      "new_path": "deploy/nuvolaris-permissions/whisk-user-crd.yaml"
    },
    {
      "type": "modify",
      "old_id": "2987af3c2cbe99bc0ae39e73ab9d92fa0c005611",
      "old_mode": 33188,
      "old_path": "nuvolaris/kvrocks.py",
      "new_id": "d83028425eee2e26fa1a4c4067588e2ffe0df04d",
      "new_mode": 33188,
      "new_path": "nuvolaris/kvrocks.py"
    },
    {
      "type": "modify",
      "old_id": "58c5ea9951637914e879bb7acd1af4c9f7428a17",
      "old_mode": 33188,
      "old_path": "nuvolaris/mongodb.py",
      "new_id": "210a0085adb1679542b4c526dea18b9ff3a3b236",
      "new_mode": 33188,
      "new_path": "nuvolaris/mongodb.py"
    },
    {
      "type": "modify",
      "old_id": "7274e871dbb9bee0b03fea2155bc933d78931b13",
      "old_mode": 33188,
      "old_path": "nuvolaris/postgres_operator.py",
      "new_id": "b11d245e5f17a80f09447c153ca241f46c906cf2",
      "new_mode": 33188,
      "new_path": "nuvolaris/postgres_operator.py"
    },
    {
      "type": "modify",
      "old_id": "89be2c148df607b75c2c0844fa8f7e93d4056f56",
      "old_mode": 33188,
      "old_path": "nuvolaris/seaweedfs_util.py",
      "new_id": "3c1aebc7b8b73a0f1c3cb9bd5f00f6095bd2603b",
      "new_mode": 33188,
      "new_path": "nuvolaris/seaweedfs_util.py"
    },
    {
      "type": "modify",
      "old_id": "34a1bb2723c00288a93f8f0caed2763a10744f88",
      "old_mode": 33188,
      "old_path": "nuvolaris/util.py",
      "new_id": "aa7667d4a9d3a5b065a26c575c4d1d0b82472738",
      "new_mode": 33188,
      "new_path": "nuvolaris/util.py"
    }
  ]
}
