Skip to content

refactor(actual-budget): make user namespaces permanent and retire the pilot component - #5857

Merged
devantler merged 2 commits into
mainfrom
claude/actual-budget-permanent-user-namespaces-3605
Nov 4, 2026
Merged

devantler merged 2 commits into
mainfrom
claude/actual-budget-permanent-user-namespaces-3605

Conversation

@devantler

Copy link
Copy Markdown
Contributor

Why

Actual Budget has run in its own user namespace (hostUsers: false) since 17 September, as a pilot. Its runtime verdict passed on #3604: the kernel id maps of both containers were read from the live pod and are not the host's. The pilot was always meant to end with the setting made permanent and its temporary component retired, in a separate reviewed change. This is that change.

What

  • The pilot component is replaced by two ordinary production patches in the Hetzner apps overlay: the namespace label for the existing admission rule and the Helm post-renderer that sets hostUsers: false. They render exactly the same objects as before. The apps layer build is byte-identical to main, so production sees no change and the pod does not restart.
  • The render regression now checks the permanent setting. It still proves rollback by removing both patches, that storage and both containers stay identical, and that the local overlay is untouched.
  • The setting is documented next to its patches, and the base README points there.

The database volume, container identities, mounts, authentication settings and the single-writer Recreate strategy are unchanged.

Validation

  • kubectl kustomize k8s/providers/hetzner/apps is byte-identical before and after (cmp).
  • bash scripts/tests/test-actual-budget-user-namespaces.sh passes. Four negative controls fail as intended: a missing label patch, a widened patch target, a patch that no longer sets hostUsers: false, and a duplicated label patch.
  • ksail workload validate and ksail --config ksail.prod.yaml workload validate pass with no failures (138 kustomizations, 770 files). shellcheck and the organization naming validator pass.

Fixes #3605

🤖 Generated with Claude Code

…e pilot component

The Actual Budget user-namespace pilot passed its runtime verdict on
#3604. Replace its temporary component with two ordinary production
patches, the namespace label and the hostUsers post-renderer, that
render the same objects byte for byte. Adapt the render regression to
the permanent setting while keeping its rollback and storage checks, and
document the setting next to the patches.

Fixes #3605

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

@codex review

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-11-04T15:21:32.005749Z
We couldn’t complete this review. Comment @codex review to try again.
16999ba Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: f71156ab09

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@devantler

Copy link
Copy Markdown
Contributor Author

Tried as a user, at f71156ab.

  • kubectl kustomize k8s/providers/hetzner/apps is byte-identical to main (cmp). The production apps layer therefore applies exactly what it applies today.
  • A read-only check of production shows the state this branch declares. The actual-budget namespace has pod-security.devantler.tech/user-namespaces=enabled. The running pod has hostUsers=false with both containers ready. The HelmRelease's last post-renderer is the hostUsers: false patch.
  • bash scripts/tests/test-actual-budget-user-namespaces.sh passes. It fails as intended when the label patch is missing or duplicated, when the pod patch target is widened, and when the patch stops setting hostUsers: false.

🤖 Generated with Claude Code

@devantler

Copy link
Copy Markdown
Contributor Author

Status: held as a draft. The Codex review at the current head is clean. This change can't merge yet for two reasons outside it:

  1. Since 3 November every pull request here must pass the organization Validate Go Project workflow (Every pull request is blocked by the organization Go workflow since GitHub reclassified this repository as Go #5852). Its MegaLinter job scans the whole repository and currently fails on files this PR doesn't touch, as seen on fix(ci): validate against the current CRD catalogue again #5854 (betterleaks, checkov). ci: pass the organization Go workflow across the repository #5853 is fixing that.
  2. The merge queue already holds ten or more entries.

Next steps: once #5853 merges, update this branch from main, confirm every required check is green at the new head, re-request review at that head, then promote and enqueue it. Enqueue only one platform PR at a time, while platform-live-health.sh passes.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

❌MegaLinter analysis: Error

❌ REPOSITORY / betterleaks - 11 errors
19.2-downstream-cleanup.patch
│   resource ...... fs.content
└○


┌─generic-api-key──○
│
│ 385 │ +google.golang.org/api v0.290.0 h1:REDACTED
│     │                                    ^^^^^^^^
│
│ attributes:
│   path .......... k8s/bases/infrastructure/controllers/kyverno/background-v1.19.2-downstream-cleanup.patch
│   resource ...... fs.content
└○


┌─curl-auth-user──○
│
│ 143 │ docker exec "$name" curl --fail --silent --show-error --max-time 5 \
│ 144 │   --user REDACTED \
│     │          ^^^^^^^^
│
│ attributes:
│   path .......... scripts/tests/test-private-mail-server.sh
│   resource ...... fs.content
└○


┌─curl-auth-user──○
│
│ 149 │ status="$(docker exec "$name" curl --silent --max-time 5 --output /dev/null --write-out '%{…
│ 150 │   --user REDACTED --header 'Content-Type: application/json' \
│     │          ^^^^^^^^
│
│ attributes:
│   path .......... scripts/tests/test-private-mail-server.sh
│   resource ...... fs.content
└○


┌─slack-webhook-url──○
│
│ 48 │ # `REDACTED` matched both expressions,
│    │    ^^^^^^^^
│
│ attributes:
│   path .......... scripts/tests/test-trivyignore-configmap-content-boundary.sh
│   resource ...... fs.content
└○


┌─slack-webhook-url──○
│
│ 249 │   'REDACTED'
│     │    ^^^^^^^^
│
│ attributes:
│   path .......... scripts/tests/test-trivyignore-configmap-content-boundary.sh
│   resource ...... fs.content
└○


┌─generic-api-key──○
│
│ 571 │ …VkLWlk",SECRET_ACCESS_KEY:"REDACTED",REGION:"YXV0bw=="}}' >"${CASE}/dedicated-secret.json"
│     │                             ^^^^^^^^
│
│ attributes:
│   path .......... scripts/tests/test-verify-wedding-backup-denial.sh
│   resource ...... fs.content
└○


┌─curl-auth-user──○
│
│ 216 │     --entrypoint curl "$server" --disable "$@"
│ 217 │ }
│ 218 │ inventory() {
│     │ … (1 more lines)
│ 220 │     --user REDACTED --header 'Content-Type: application/json' \
│     │            ^^^^^^^^
│
│ attributes:
│   path .......... scripts/tests/test-private-mail-configuration.sh
│   resource ...... fs.content
└○


11:41PM INF scanned ~19765359 bytes (19.77 MB) in 1.36s
11:41PM WRN leaks found: 11

(Truncated to last 2105 characters out of 3340)
❌ REPOSITORY / checkov - 27 errors
"--help"]
github_actions scan results:

Passed checks: 941, Failed checks: 3, Skipped checks: 0

Check: CKV_GHA_7: "The build output cannot be affected by user parameters other than the build entry point and the top-level source location. GitHub Actions workflow_dispatch inputs MUST be empty. "
	FAILED for resource: on(Verify Alert Publisher App)
	File: /.github/workflows/verify-alert-publisher-app.yaml:9-15

		9  |       confirm:
		10 |         description: "Type exactly: verify-alert-publisher-read-only"
		11 |         required: true
		12 |         type: string
		13 | 
		14 | permissions: {}
		15 | 

Check: CKV_GHA_7: "The build output cannot be affected by user parameters other than the build entry point and the top-level source location. GitHub Actions workflow_dispatch inputs MUST be empty. "
	FAILED for resource: on(🗂️ Stale Issue Triage)
	File: /.github/workflows/stale-issues.yaml:11-17

		11 |       dry-run:
		12 |         description: Preview without changing issues or saved progress.
		13 |         type: boolean
		14 |         default: true
		15 | 
		16 | permissions: {}
		17 | 

Check: CKV_GHA_7: "The build output cannot be affected by user parameters other than the build entry point and the top-level source location. GitHub Actions workflow_dispatch inputs MUST be empty. "
	FAILED for resource: on(Prove Cilium Default Deny)
	File: /.github/workflows/prove-cilium-default-deny.yaml:8-26

		8  |       confirm:
		9  |         description: Type RUN_DISPOSABLE_CILIUM_PROOF after approving this run
		10 |         required: true
		11 |         type: string
		12 |       workflow_head:
		13 |         description: Exact approved main SHA containing the proof workflow
		14 |         required: true
		15 |         type: string
		16 |       candidate_pr:
		17 |         description: Trusted same-repository candidate PR number
		18 |         required: true
		19 |         type: string
		20 |       candidate_head:
		21 |         description: Exact 40-character candidate PR head SHA
		22 |         required: true
		23 |         type: string
		24 | 
		25 | permissions: {}
		26 |

(Truncated to last 2105 characters out of 21015)
❌ HTML / djlint - 8 errors
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H011 Attribute values should be quoted.
::warning file=scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html,line=1::H025 Tag seems to be an orphan.
❌ REPOSITORY / grype - 38 errors
8th)   < 0.1  
golang.org/x/net                                                 v0.61.0                             0.62.0                                go-module  GO-2026-6860         Unknown   0.2% (8th)   < 0.1  
go.opentelemetry.io/otel/exporters/otlp/otlptrace                v1.43.0                             1.45.0                                go-module  GHSA-8wmf-6v46-5gfg  Low       0.3% (18th)  < 0.1  
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc  v1.42.0                             1.45.0                                go-module  GHSA-8wmf-6v46-5gfg  Low       0.3% (18th)  < 0.1  
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp  v1.43.0                             1.45.0                                go-module  GHSA-8wmf-6v46-5gfg  Low       0.3% (18th)  < 0.1  
go.opentelemetry.io/otel/sdk                                     v1.44.0                             1.45.0                                go-module  GHSA-8wmf-6v46-5gfg  Low       0.3% (18th)  < 0.1  
github.com/google/cel-go                                         v0.26.0                             0.29.0                                go-module  GHSA-gcjh-h69q-9w9g  Medium    N/A          N/A    
github.com/chrismellard/docker-credential-acr-env                v0.0.0-20230304212654-82a0ddb27589                                        go-module  GO-2026-6225         Unknown   N/A          N/A    
golang.org/x/crypto                                              v0.54.0                             0.58.1-0.20261009181718-2f1f834330b2  go-module  GO-2026-5932         Unknown   N/A          N/A    
golang.org/x/crypto                                              v0.57.0                             0.58.1-0.20261009181718-2f1f834330b2  go-module  GO-2026-5932         Unknown   N/A          N/A    
golang.org/x/crypto                                              v0.58.0                             0.58.1-0.20261009181718-2f1f834330b2  go-module  GO-2026-5932         Unknown   N/A          N/A
[0221] ERROR discovered vulnerabilities at or above the severity threshold

(Truncated to last 2105 characters out of 10921)
❌ DOCKERFILE / hadolint - 1 error
k8s/bases/infrastructure/controllers/kyverno/BackgroundDownstreamCleanup.Dockerfile:32 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile:33 DL4006 warning: Set the SHELL option -o pipefail before RUN with a pipe in it. If you are using /bin/sh in an alpine image or if your shell is symlinked to busybox then consider explicitly setting your SHELL to /bin/ash, or disable this check
k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile:49 DL3059 info: Multiple consecutive `RUN` instructions. Consider consolidation.
k8s/bases/infrastructure/coroot/CorootCheckpoint.Dockerfile:9 DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`
❌ HTML / htmlhint - 21 errors
ico...
                                                     ^ The value of attribute [ href ] must be in double quotes. (attr-value-double-quotes)
      L1 |...icon-16x16.png><link rel="shortcut icon" href=favicon.ico><script defer src=bundle.main.60a3ef75467cd...
                                                     ^ The value of attribute [ href ] must be in double quotes. (attr-value-double-quotes)
      L1 |...cut icon" href=favicon.ico><script defer src=bundle.main.60a3ef75467cd3b8a057.js></script><link href=...
                                                     ^ The value of attribute [ src ] must be in double quotes. (attr-value-double-quotes)
      L1 |...nk rel="shortcut icon" href=favicon.ico><script defer src=bundle.main.60a3ef75467cd3b8a057.js></scrip...
                                                     ^ The <script> tag cannot be used in a <head> tag. (head-script-disabled)
      L1 |...n.60a3ef75467cd3b8a057.js></script><link href=bundle.main.841ee8bbb7cc9d85b79e.css rel=stylesheet></h...
                                                     ^ The value of attribute [ href ] must be in double quotes. (attr-value-double-quotes)
      L1 |...ref=bundle.main.841ee8bbb7cc9d85b79e.css rel=stylesheet></head><body><div id=app class=test></div></b...
                                                     ^ The value of attribute [ rel ] must be in double quotes. (attr-value-double-quotes)
      L1 |...79e.css rel=stylesheet></head><body><div id=app class=test></div></body></html>
                                                     ^ The value of attribute [ id ] must be in double quotes. (attr-value-double-quotes)
      L1 |... rel=stylesheet></head><body><div id=app class=test></div></body></html>
                                                     ^ The value of attribute [ class ] must be in double quotes. (attr-value-double-quotes)
      L1 |...ody><div id=app class=test></div></body></html>
                                                     ^ Tag must be paired, no start tag: [ </html> ] (tag-pair)

Scanned 1 files, found 21 errors in 1 files (32 ms)

(Truncated to last 2105 characters out of 5427)
❌ REPOSITORY / osv-scanner - 1 error
| 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6607 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6608 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6610 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6611 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6612 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6613 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6617 |      | Go        | stdlib                     | 1.24.0  | 1.26.9        | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2026-6809 |      | Go        | stdlib                     | 1.24.0  | 1.26.10       | scripts/tests/fixtures/govulncheck-negative-control/go.mod |
| https://osv.dev/GO-2025-3615 |      | Go        | github.com/kyverno/kyverno | 1.19.2  | --            | scripts/tests/tenant-webapp-admission/go.mod               |
| https://osv.dev/GO-2026-5337 |      | Go        | github.com/kyverno/kyverno | 1.19.2  | --            | scripts/tests/tenant-webapp-admission/go.mod               |
| https://osv.dev/GO-2026-5594 |      | Go        | github.com/kyverno/kyverno | 1.19.2  | --            | scripts/tests/tenant-webapp-admission/go.mod               |
+------------------------------+------+-----------+----------------------------+---------+---------------+------------------------------------------------------------+

(Truncated to last 2105 characters out of 9312)
❌ GO / revive - 1 error
ckup-catalogue/coverage.go:1:1: should have a package comment
scripts/verify-email-data-recovery/image.go:1:1: should have a package comment
scripts/prove-longhorn-ui-readonly/main.go:1:1: should have a package comment
scripts/prove-kyverno-cache-recovery/service.go:1:1: should have a package comment
scripts/migrate-longhorn-v2/benchmark_recovery_no_start.go:1:1: should have a package comment
scripts/expand-openbao-audit/main.go:206:3: redefinition of the built-in function cap
scripts/expand-openbao-audit/main.go:283:2: redefinition of the built-in function copy
internal/backupcatalogue/catalogue.go:1:1: should have a package comment
internal/backupcatalogue/catalogue.go:25:6: exported type Catalogue should have comment or be unexported
scripts/diagnose-email-startup/access.go:1:1: should have a package comment
internal/longhorninventory/block_layout.go:1:1: should have a package comment
internal/longhorninventory/block_layout.go:16:6: exported type BlockLayoutReport should have comment or be unexported
internal/longhorninventory/block_layout.go:29:1: exported method Native.ListBlockLayout should have comment or be unexported
scripts/observe-historical-longhorn-backups/runtime.go:1:1: should have a package comment
scripts/validate-eks-ci-role-policy/approval_summary.go:1:1: should have a package comment
scripts/verify-email-data-recovery/observation_test.go:81:55: parameter 'w' seems to be unused, consider removing or renaming it as _
scripts/private-mail-config/bootstrap.go:1:1: should have a package comment
scripts/verify-arc-app-identity/config.go:1:1: should have a package comment
scripts/verify-email-data-recovery/main.go:1:1: should have a package comment
scripts/migrate-longhorn-v2/node.go:1:1: should have a package comment
scripts/prove-scoped-package-access/main_test.go:82:76: parameter 'r' seems to be unused, consider removing or renaming it as _
scripts/prove-scoped-package-access/main_test.go:238:16: parameter 'ctx' seems to be unused, consider removing or renaming it as _
scripts/migrate-longhorn-v2/inventory_temporary.go:1:1: should have a package comment

(Truncated to last 2105 characters out of 34871)
❌ REPOSITORY / secretlint - 1 error
scripts/tests/test-verify-wedding-backup-denial.sh
  431:26  error  [BasicAuth] found basic auth credential: *****************************************************  @secretlint/secretlint-rule-preset-recommend > @secretlint/secretlint-rule-basicauth

✖ 1 problem (1 error, 0 warnings, 0 infos)
❌ BASH / shellcheck - 1 error
In scripts/bootstrap-tenant-source.sh line 247:
  [ -r "$OUTPUT" ] && [ ! -L "$OUTPUT" ] || return 1
        ^-----^ SC2153 (info): Possible misspelling: OUTPUT may not be assigned. Did you mean output?

For more information:
  https://www.shellcheck.net/wiki/SC2153 -- Possible misspelling: OUTPUT may ...
❌ REPOSITORY / trivy - 1 error
See https://avd.aquasec.com/misconfig/ksv-0118
────────────────────────────────────────
 scripts/tests/fixtures/coroot-dns-probe/pod.yaml:11-12
────────────────────────────────────────
  11 ┌     - name: fixture
  12 └       image: registry.k8s.io/pause:3.10
────────────────────────────────────────


KSV-0118 (HIGH): pod coroot-dns-probe in observability namespace is using the default security context, which allows root privileges
════════════════════════════════════════
Security context controls the allocation of security parameters for the pod/container/volume, ensuring the appropriate level of protection. Relying on default security context may expose vulnerabilities to potential attacks that rely on privileged access.

See https://avd.aquasec.com/misconfig/ksv-0118
────────────────────────────────────────
 scripts/tests/fixtures/coroot-dns-probe/pod.yaml:9-12
────────────────────────────────────────
   9 ┌ spec:
  10 │   containers:
  11 │     - name: fixture
  12 └       image: registry.k8s.io/pause:3.10
────────────────────────────────────────



scripts/tests/fixtures/wedding-database-priority/cluster.yaml (kubernetes)
==========================================================================
Tests: 118 (SUCCESSES: 117, FAILURES: 1)
Failures: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

KSV-0040 (LOW): A resource quota policy with hard memory and CPU limits should be configured per namespace
════════════════════════════════════════
Ensure that a ResourceQuota policy is configured to limit aggregate resource usage within a namespace

See https://avd.aquasec.com/misconfig/ksv-0040
────────────────────────────────────────
 scripts/tests/fixtures/wedding-database-priority/cluster.yaml:6-15
────────────────────────────────────────
   6 ┌ spec:
   7 │   instances: 3
   8 │   storage:
   9 │     size: 1Gi
  10 │     storageClass: longhorn-wffc
  11 │   plugins:
  12 │     - name: barman-cloud.cloudnative-pg.io
  13 │       isWALArchiver: true
  14 │       parameters:
  15 └         barmanObjectName: dedicated-backups
────────────────────────────────────────

(Truncated to last 2105 characters out of 984376)
❌ YAML / v8r - 1 error
✖ scripts/tests/fixtures/wedding-database-priority/cluster.yaml is invalid

scripts/tests/fixtures/wedding-database-priority/cluster.yaml# must NOT have additional properties, found additional property 'apiVersion'
scripts/tests/fixtures/wedding-database-priority/cluster.yaml# must NOT have additional properties, found additional property 'kind'
scripts/tests/fixtures/wedding-database-priority/cluster.yaml# must NOT have additional properties, found additional property 'metadata'
scripts/tests/fixtures/wedding-database-priority/cluster.yaml# must NOT have additional properties, found additional property 'spec'
❌ YAML / yamllint - 293 errors
--"  (document-start)

tests/restrict-arc-retirement-secret-uninstalled/kyverno-test.yaml
  6:1       warning  missing document start "---"  (document-start)

tests/restrict-arc-retirement-secret-uninstalled/resources.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-tenant-network-policies/node-group-resources.yaml
  4:1       warning  missing document start "---"  (document-start)

tests/restrict-tenant-webapps/kyverno-test.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-tenant-webapps/resources.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-tenant-webapps/user-info.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-deletion/kyverno-test.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-deletion/ordinary-writer/kyverno-test.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-deletion/resources.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-deletion/values.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-ownership/kyverno-test.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-ownership/resources.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/restrict-webapp-child-ownership/user-info.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/validate-pdb-drain-safe/kyverno-test.yaml
  5:1       warning  missing document start "---"  (document-start)

tests/validate-pdb-drain-safe/resources.yaml
  1:1       warning  missing document start "---"  (document-start)

tests/validate-replica-ceiling/kyverno-test.yaml
  7:1       warning  missing document start "---"  (document-start)

tests/validate-replica-ceiling/resources.yaml
  1:1       warning  missing document start "---"  (document-start)

(Truncated to last 2105 characters out of 32419)
❌ ACTION / zizmor - 40 errors
a4bc0b73d1f32bc45510 # v3.3.0
    |               ------------------------------------------------------------------------ app token requested here
...
203 |           owner: devantler-tech
    |           ^^^^^^^^^^^^^^^^^^^^^ token granted access to all repositories for this owner's app installation
    |
    = note: audit confidence → High
    = tip: use `repositories: 'repo1,repo2'` to scope the token to specific repositories
    = help: audit documentation → https://docs.zizmor.sh/audits/#github-app

error[github-app]: dangerous use of GitHub App tokens
  --> .github/workflows/regenerate-publish-workflow-approved-revisions.yaml:78:11
   |
66 |         uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
   |               ------------------------------------------------------------------------ app token requested here
...
78 |           owner: ${{ github.repository_owner }}
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ token granted access to all repositories for this owner's app installation
   |
   = note: audit confidence → High
   = tip: use `repositories: 'repo1,repo2'` to scope the token to specific repositories
   = help: audit documentation → https://docs.zizmor.sh/audits/#github-app

error[github-app]: dangerous use of GitHub App tokens
  --> .github/workflows/regenerate-publish-workflow-approved-revisions.yaml:98:11
   |
91 |         uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
   |               ------------------------------------------------------------------------ app token requested here
...
98 |           owner: ${{ github.repository_owner }}
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ token granted access to all repositories for this owner's app installation
   |
   = note: audit confidence → High
   = tip: use `repositories: 'repo1,repo2'` to scope the token to specific repositories
   = help: audit documentation → https://docs.zizmor.sh/audits/#github-app

40 findings (35 suppressed): 0 informational, 0 low, 0 medium, 5 high
No fixes available to apply.

(Truncated to last 2105 characters out of 9984)
⚠️ BASH / bash-exec - 18 errors
te-publish-workflow-matchers.sh
✅ [SUCCESS] scripts/update-vendored-operators.sh
✅ [SUCCESS] scripts/use-prod-stable-api-endpoint.sh
✅ [SUCCESS] scripts/validate-alert-coverage.sh
✅ [SUCCESS] scripts/validate-embedded-json.sh
✅ [SUCCESS] scripts/validate-homepage-bookmarks.sh
✅ [SUCCESS] scripts/validate-image-verifier-liveness.sh
✅ [SUCCESS] scripts/validate-kyverno-fixture-evaluation.sh
❌ [ERROR] scripts/validate-webapp-inputs.sh
    Error: File:[scripts/validate-webapp-inputs.sh] is not executable

✅ [SUCCESS] scripts/verify-arc-transport.sh
✅ [SUCCESS] scripts/verify-data-product-rollout.sh
❌ [ERROR] scripts/verify-email-provider/probe-client.sh
    Error: File:[scripts/verify-email-provider/probe-client.sh] is not executable

❌ [ERROR] scripts/verify-email-provider/run.sh
    Error: File:[scripts/verify-email-provider/run.sh] is not executable

✅ [SUCCESS] scripts/verify-gateway-routes-applied.sh
✅ [SUCCESS] scripts/verify-heartbeat-cleanup.sh
✅ [SUCCESS] scripts/verify-image-unsigned.sh
✅ [SUCCESS] scripts/verify-kubelet-config-readback.sh
✅ [SUCCESS] scripts/verify-matcher-accepts-digest.sh
❌ [ERROR] scripts/verify-private-mail-storage-recovery.sh
    Error: File:[scripts/verify-private-mail-storage-recovery.sh] is not executable

✅ [SUCCESS] scripts/verify-prod-recovery-source.sh
✅ [SUCCESS] scripts/verify-published-evidence.sh
❌ [ERROR] scripts/verify-shared-backup-consumers.sh
    Error: File:[scripts/verify-shared-backup-consumers.sh] is not executable

✅ [SUCCESS] scripts/verify-talos-schematic-readback.sh
✅ [SUCCESS] scripts/verify-umami-tracking.sh
✅ [SUCCESS] scripts/verify-wedding-backup-cutover.sh
✅ [SUCCESS] scripts/verify-wedding-backup-denial-pod.sh
✅ [SUCCESS] scripts/verify-wedding-backup-denial.sh
✅ [SUCCESS] scripts/verify-wedding-shared-backup-coverage-pod.sh
✅ [SUCCESS] scripts/verify-wedding-shared-backup-coverage.sh
✅ [SUCCESS] scripts/wait-for-platform-flux-revision.sh
✅ [SUCCESS] scripts/wait-for-prod-api-stability.sh
✅ [SUCCESS] scripts/write-publish-workflow-matchers.sh
✅ [SUCCESS] tests/kyverno-stale-report-prune/assert-probe-result.sh


(Truncated to last 2105 characters out of 25906)
⚠️ SPELL / cspell - 1 error
"unrelatedlike",
        "unrenderable",
        "unreplicated",
        "unrequested",
        "unretained",
        "unretried",
        "unreviewable",
        "unreviewed",
        "unrewritten",
        "unrouted",
        "unrun",
        "unscanned",
        "unshippable",
        "unshortened",
        "unsignalled",
        "unstarted",
        "unstubbed",
        "unsuspended",
        "untraversable",
        "unvalidated",
        "unwaited",
        "unwired",
        "upbound",
        "updatekeys",
        "upjet",
        "uprobe",
        "uprobes",
        "urandom",
        "urlencode",
        "usec",
        "userinfo",
        "userns",
        "ushfn",
        "validatable",
        "validatingadmissionpolicies",
        "validatingadmissionpolicybindings",
        "validatingpolicy",
        "validatingwebhookconfigurations",
        "valuesfrom",
        "vanything",
        "vcluster",
        "vcunav",
        "velero",
        "verticalpodautoscalers",
        "vfio",
        "virt",
        "volumeattachments",
        "volumeconfig",
        "volumesnapshot",
        "volumestatus",
        "vpas",
        "vpol",
        "vpolengine",
        "vulnerabilitymanifests",
        "vulnerabilitymanifestsummaries",
        "vulnerabilitymanifestsummary",
        "vulns",
        "wailsapp",
        "wals",
        "webadmin",
        "webapps",
        "webui",
        "wffc",
        "wgpolicyk",
        "wildcarding",
        "wlan",
        "wlid",
        "workloadconfigurationscan",
        "workloadconfigurationscans",
        "workloadconfigurationscansummaries",
        "workloadconfigurationscansummary",
        "worktree",
        "worktrees",
        "wraparg",
        "wrapctl",
        "wrapopt",
        "wrongns",
        "xcheckov",
        "xcrun",
        "xcrun's",
        "xform",
        "xlated",
        "xpkg",
        "xprov",
        "yannh",
        "yubikey",
        "yzwvjjmcyfnl",
        "zizmor",
        "\u017ftatus"
    ]
}


You can also copy-paste megalinter-reports/.cspell.json at the root of your repository

(Truncated to last 2105 characters out of 2284652)
⚠️ COPYPASTE / jscpd - 646 errors
hared-backup-coverage.sh [302:5 - 329:12]
Clone found (bash)
 - scripts/verify-wedding-backup-denial.sh [282:49 - 294:16] (13 lines, 54 tokens)
   scripts/verify-wedding-shared-backup-coverage.sh [331:62 - 343:16]
┌────────────┬────────────────┬─────────────┬──────────────┬──────────────┬──────────────────┬───────────────────┐
│ Format     │ Files analyzed │ Total lines │ Total tokens │ Clones found │ Duplicated lines │ Duplicated tokens │
├────────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ bash       │ 406            │ 116703      │ 621939       │ 208          │ 2585 (2.22%)     │ 18343 (2.95%)     │
├────────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ diff       │ 14             │ 7274        │ 83186        │ 57           │ 447 (6.15%)      │ 7975 (9.59%)      │
├────────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ go         │ 638            │ 153628      │ 1193099      │ 381          │ 3113 (2.03%)     │ 28823 (2.42%)     │
├────────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ javascript │ 9              │ 694         │ 12086        │ 0            │ 0 (0.00%)        │ 0 (0.00%)         │
├────────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ txt        │ 3              │ 2153        │ 15835        │ 0            │ 0 (0.00%)        │ 0 (0.00%)         │
├────────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ Total:     │ 1070           │ 280452      │ 1926145      │ 646          │ 6145 (2.19%)     │ 55141 (2.86%)     │
└────────────┴────────────────┴─────────────┴──────────────┴──────────────┴──────────────────┴───────────────────┘
Found 646 clones.
HTML report saved to megalinter-reports/copy-paste/jscpd-report.html
ERROR: jscpd found too many duplicates (2.2%) over threshold (0.0%)
time: 6.11s

(Truncated to last 2105 characters out of 121011)
⚠️ SPELL / lychee - 37 errors
thub/workflows/verify-email-credential-custody.yaml
[ERROR] http://127.0.0.1:38200/ (at 109:27) | Error (cached)
[ERROR] http://127.0.0.1:38200/v1/sys/health (at 102:17) | Error (cached)

Errors in .github/workflows/verify-email-storage-key-recovery.yaml
[ERROR] http://127.0.0.1:38200/v1/sys/health (at 109:17) | Error (cached)

Errors in .github/workflows/verify-openbao-backup-recovery.yaml
[ERROR] http://127.0.0.1:38200/v1/sys/health (at 113:17) | Error (cached)

Errors in docs/costs.md
[404] https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/#cloud-servers (at 24:27) | Rejected status code: 404 Not Found

Errors in scripts/check-hubble-ui-streaming/testdata/frontend-v0.13.6-index.html
[ERROR] error: (at 1:78) | Cannot resolve root-relative link '/': To resolve root-relative links in local files, provide a root dir
[ERROR] file://scripts/check-hubble-ui-streaming/testdata/bundle.main.841ee8bbb7cc9d85b79e.css (at 1:536) | File not found. Check if file exists and path is correct
[ERROR] file://scripts/check-hubble-ui-streaming/testdata/favicon-16x16.png (at 1:401) | File not found. Check if file exists and path is correct
[ERROR] file://scripts/check-hubble-ui-streaming/testdata/favicon-32x32.png (at 1:336) | File not found. Check if file exists and path is correct
[ERROR] file://scripts/check-hubble-ui-streaming/testdata/favicon.ico (at 1:450) | File not found. Check if file exists and path is correct

Errors in talos/control-planes/wireguard.yaml
[404] https://docs.siderolabs.com/talos/v1.13/reference/configuration/network/deviceconfig/ (at 48:5) | Rejected status code: 404 Not Found | Followed 1 redirect. Redirects: https://docs.siderolabs.com/talos/v1.13/reference/configuration/network/deviceconfig/ --[308]--> https://docs.siderolabs.com/talos/v1.13/reference/configuration/network/deviceconfig

Hint: Followed 12 redirects. You might want to consider replacing redirecting URLs with the resolved URLs. Use verbose mode (`-v`/`-vv`) to see redirection details.
Hint: You can configure accepted/rejected response codes with `-a` or `--accept`

(Truncated to last 2105 characters out of 6291)
⚠️ MARKDOWN / markdownlint - 100 errors
Line length [Expected: 400; Actual: 505]
k8s/bases/README.md:10:141 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
k8s/bases/README.md:11:39 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
k8s/bases/README.md:11:138 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
k8s/providers/README.md:8:91 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
k8s/providers/README.md:8:207 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
k8s/providers/README.md:9:234 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
scripts/alert-publisher/README.md:90 error MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "4683. It uses the maintained A..."]
scripts/alert-publisher/README.md:90:75 error MD026/no-trailing-punctuation Trailing punctuation in heading [Punctuation: ',']
scripts/alert-publisher/README.md:161 error MD001/heading-increment Heading levels should only increment by one level at a time [Expected: h2; Actual: h3]
scripts/judge-openbao-quorum/README.md:25:401 error MD013/line-length Line length [Expected: 400; Actual: 437]
scripts/README.md:15:159 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
scripts/README.md:16:185 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
scripts/README.md:18:98 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
scripts/README.md:18:171 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
scripts/README.md:20:255 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]

(Truncated to last 2105 characters out of 11292)

✅ Linters with no issues

actionlint, git_diff, jsonlint, prettier (8 fixes), prettier (20 fixes), shfmt (172 fixes), syft, trivy-sbom, trufflehog, v8r

Notices

⚠️ Your configuration references items that have been removed from MegaLinter and are ignored: REPOSITORY_GITLEAKS. See Removed linters to find their replacements.

See detailed reports in MegaLinter artifacts

MegaLinter is provided by OX Security
Show us your support by starring ⭐ the repository

@devantler

devantler commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Blocker: none

Cleared 2026-11-04: platform#5853 merged 2026-11-04T08:01Z; the organization Go workflow passes on main again and pull requests can pass their required checks (platform#5852 status 2026-11-04)

Previous record (historical):

> 🤖 Generated by the Agentic Engineer

<!-- pr-blocker-record -->

**Blocker:** devantler-tech/platform#5852 | upstream | last-verified 2026-11-04: open; this PR's only red check is the repository-wide organization Go workflow lint (identical zizmor/shellcheck/hadolint/revive/djlint/htmlhint findings on every platform PR), which platform#5853 is fixing; update from main after it merges

…permanent-user-namespaces-3605

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@devantler

Copy link
Copy Markdown
Contributor Author

@codex review

🤖 Generated with Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@devantler devantler removed the blocked label Nov 4, 2026

@devantler devantler left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Generated by the Agentic Engineer (interactive Claude Code session)

Self-review (fallback — CodeRabbit, Codex and Cursor Bugbot unavailable)

Reviewed commit: 16999ba

  • CodeRabbit: rate-limited for this organisation since 2026-11-03 09:04Z (batch lane check); not requested.
  • Codex: answered the 2026-11-04 request for this head with its code-review usage-limit message instead of a review.
  • Cursor Bugbot: reached its usage limit at 2026-11-04 00:28Z; no review since.

Scope: the whole diff against main at this head, including the main merge. The retired component's two JSON patches are now two ordinary production patches with the same targets and values (namespace label; appended hostUsers: false post-renderer on the Actual Budget HelmRelease only). kubectl kustomize k8s/providers/hetzner/apps is byte-identical to main, so production applies nothing new and the pod does not restart. No file still references the removed component path. The regression now pins each patch entry exactly once and the pod patch's exact target, and its rollback/re-enable round trip still passes. Not blocking: scripts/read-actual-budget-userns-maps.sh's header still calls the setting a pilot; that is wording only.

Verdict: no P0/P1 findings

🤖 Generated with Claude Code

@devantler

Copy link
Copy Markdown
Contributor Author

Tried as a user, at 16999ba2 (after merging main).

  • kubectl kustomize k8s/providers/hetzner/apps at this head is byte-identical to current main (cmp). Production applies exactly what it applies today, so the pod does not restart.
  • bash scripts/tests/test-actual-budget-user-namespaces.sh passes at this head.
  • A read-only check of production shows the state this branch declares: the actual-budget namespace carries pod-security.devantler.tech/user-namespaces=enabled, and the running pod has hostUsers=false with both containers ready.

🤖 Generated with Claude Code

@devantler
devantler marked this pull request as ready for review November 4, 2026 15:38
@devantler
devantler added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 0b2272f Nov 4, 2026
53 checks passed
@devantler
devantler deleted the claude/actual-budget-permanent-user-namespaces-3605 branch November 4, 2026 18:18
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Retire the Actual Budget user-namespace pilot gate after evaluation

1 participant