Compare commits

..
Author SHA1 Message Date
Jørgen StensrudandClaude Fable 5.1 46eab199ee Add forte-cli public device-code Keycloak client
/ test (pull_request) Successful in 7s
Add a shared public client `forte-cli` to the `forte` realm so downloaded
skills (forte-drop first) can do RFC 8628 device-code login through the
Auth Sidecar. Today no client in the realm has the device grant enabled,
so the flow cannot start.

Client (inline in forte-realm.json, imported verbatim by keycloak-config-cli):
- publicClient: true, standardFlowEnabled: false,
  directAccessGrantsEnabled: false
- attributes: oauth2.device.authorization.grant.enabled=true
- no secret, no redirectUris/webOrigins, no k8s.secret.sync

It has to go in the realm JSON because the self-service registrar
hardcodes publicClient:false/standardFlowEnabled:true and drops
attributes. Also add forte-cli to the cleanup CronJob's protected list
(belt-and-braces; it does not match the UUID pattern anyway).

Additive only: gitea/grafana/argocd and all other realm settings are
unchanged. Keycloak is deployed only via the upc-dev overlay, which
inherits base values, so this lands on id.forteapps.net.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QciXev3MtCxo3eomcfrDRW
2026-09-03 09:56:31 +02:00
24 changed files with 70 additions and 136 deletions
+3 -3
View File
@@ -30,7 +30,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v4
with: with:
submodules: true submodules: true
fetch-depth: 0 fetch-depth: 0
@@ -40,11 +40,11 @@ jobs:
run: git submodule update --remote --merge run: git submodule update --remote --merge
- name: Run inline review - name: Run inline review
uses: docker://nikitafilonov/ai-review:v0.77.0 uses: docker://nikitafilonov/ai-review:v0.64.0
with: with:
args: ai-review run-inline args: ai-review run-inline
- name: Run summary review - name: Run summary review
uses: docker://nikitafilonov/ai-review:v0.77.0 uses: docker://nikitafilonov/ai-review:v0.64.0
with: with:
args: ai-review run-summary args: ai-review run-summary
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v7 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install TruffleHog - name: Install TruffleHog
@@ -7,8 +7,7 @@ metadata:
namespace: mcp10x namespace: mcp10x
spec: spec:
encryptedData: encryptedData:
BENKEN_CLIENT_SECRET: AgBjps8BCn20C8upAaAdb1fG4Qh3eKBbTeFuuWhQb8WoIvHmk+v03mw8i39evkQwlUWvLBWV1mtGiKwpCNhmAAdicRFG6u0m30+21K6ZtYqtKEniPKo/kjPd9nDbtxvIwiaqKs+kvFpqbxKaeqF5THYNxHZBg8gGeSbAkSx+BNIY2iLm8NRBzgC5FME5jbX8pet+DN7tbmsQTtG5f1q+h24aKXjvN5SigPft1BetfleHGlus0hFXpJ7zS4rV7rpSKSiLVV/KtS5YqEDj9uunZKyGT8j93z5xQbj0bCPVF3TU5+RCL6eE/GSgJxM4ePZ2gWZRG4eHDlGK2qE+JaNIng8wWycqLVrbs1kWoP2cdRGq6b8GHwoplAM4h4ud2fac6+5V4alhy8uhRTAX7dUG3UkwOQV/hTRb97pctPwQfltkBpDBhhW3Lfy9whSdqBuD9OqhegTqxCuWXr/P4KVOORUr0V0Iex45oLMqivI3FB2rTq9Lkwpf5YKE14d7RbKWF1G28FCNAcV8vnOIslkztLuu3GgQbVIoIiZGnnYEPofjUxbDZ/Sd1LrGeHEPR+/JJnNhNxv2297UuIIEC8kfiKuwjtLOMVQg51UbESx/+d1XmgLPqkz+jAqEPxvu8u5wO0Dov6vliTbtewJf8+fet3xnFNvyuY5ymmiTla6Gm9XPJscLj5iCzT3VhA/QuhhWXinmE/UnpYP0U4YPl5B/dUA9qT95BA6GBpDXPrDJRWNfpAH1wfG70lEBuBQXgdixYlwvx2JO6OI5+ztBKO0qFkgK FLOWCASE_TOKEN: AgAjQ0Jm779LiB2/EBKtIl18Iky/tgl7VvEvkJfr82mbe7JIp99+I8WPIMgmlXsxWBDfwJ/DZoDEAKG5o8mvwc7DtaE7LkpPSXKRIviLrm+7amNdEpwb1zKjCmZ3vNOPXLnCTD3W1od8u106MEvrZpt1N1Pzav/QUElAA4lqyf4AZPuio0H/7jF8QciVHIN4BdofodOmWWCTxP1aVMylat3txlkzuqwkXc1fKBPmOKC1qWepAG7dlQ3xJ2C5Cinz5IqOYnQPO6sm/Gp+c8yQSS+0NpKO3dp93yuwRsOLOMNpCeeYOyzn2ypFIdiBuLA5k85l5WyI9BCvRjP+kzRX+u69XL7p2eMEg+vRVfoOWNetysYCdK+96bWNVVleQEuPAFxsbJWK5eV8jTZk+QeFES8kkXQwUoTMqh+JULgONakxrzc1LmA+FtKNwHWCHalh8pLQ9KeI2i9E5CtotjHfEGLE6T0ibwwOg1ZrL3irQVII8VFm4Rk+dSicbeEMAtIaII023NWuZlonrwIIy+GSVzskhhcjV7t51hylqFA3yfb+RQCzdGYA5fySlJBWhli8IotvqnDmWduPBHGb/+yrdXHsaiDqWuUu6JBUg4JqM+AMa8FkaFh8SbctbGBoycpzLVFn9N2qWviojhC9s1NJ4MiCegvE6IsCLaHidY4UXeeGjUK6Mx6h4x3y/q7ZIrBIpUOJ+8I4Mgvi9sTCogeR+vWtpP9ZZ/31MXELuu/ho3Wn9Q==
FLOWCASE_TOKEN: AgBLN1BWnFs3R2K+Wvb37ABucQWvx8mVVDEhZiIOYYLE8SDdbshxluP4J4IISmHwLX7Q0gYWeypfTCfvMa9c5b9AEjTcpodv4CMhjp5Mq7zUCtTI6pH6QZgLhjGheKCY+RciIK1DBsNk7CZa9MuVUdd1w0/m2C7fwikPPvNDHcNLR7zBBPWVlprgRyMrsdykcm7cmWcyqTwa/55DVPPJsG9x1K2YnjzgWHlX7BoLB/Nx7qX4XVadKEXnV0jVO5isalARxvke32pwebaiFSg8EZMhe4lntOqMSP26y/9RbveeEZS8qxzoR2OmsVrHUpMeppzpVkvQ9sKi2B4Vx8XoiRY6hZR+TmZKTvFa6JKx9gwAOVs53LEUaF7+uOQOrIcFyOXm7Ibj/azf7opqfvGajygRzSUaffTIixj+M5eJnm/iua/BWarW2w4c+ZIKvQ9DhcYpnF9Gj0U7+EWfNZyzlMoLRHsOIyKNUhOeEaSLoVQGyqRY72ZGqs83EPfQYlEu74PGyXPjd11KMhAayluGLadeAH2QDyigpf7REdXAGULNDhkJrqeYMmmGCZCyrvNOoXjYC4jQQEYA4Sd4QJA05q/EW8aFE/++nY8RqhbHqDz6wshAW/WFsTsR4JC6fc5qR+YVSmjKOa7lnk7I9vD7uPEZzCc6ImvA/NxTCfDKCREvLA5G0lYsmiTuxYmBesUgCSVVMxflEl1GXvGpFniZKPyvxIdna9j7XEQjUZsGTiyN1w==
template: template:
metadata: metadata:
creationTimestamp: null creationTimestamp: null
+1 -1
View File
@@ -29,7 +29,7 @@ spec:
topologyKey: kubernetes.io/hostname topologyKey: kubernetes.io/hostname
initContainers: initContainers:
- name: gitea-dump - name: gitea-dump
image: gitea/gitea:1.27.3 image: gitea/gitea:1.25.4
command: command:
- sh - sh
- -c - -c
+20 -20
View File
@@ -1,27 +1,27 @@
{ {
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json", "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json",
"packages": [ "packages": [
"kubectl@1.36.3", "kubectl@1.33.2",
"kubernetes-helm@4.2.4", "kubernetes-helm@3.18.4",
"k9s@0.51.0", "k9s@0.50.7",
"kubeseal@0.38.4", "kubeseal@0.30.0",
"argocd@3.4.6", "argocd@2.14.11",
"kubecm@0.35.1", "kubecm@0.33.1",
"kubectl-tree@0.6.0", "kubectl-tree@0.4.3",
"kind@0.32.0", "kind@0.29.0",
"kustomize@5.8.1", "kustomize@5.7.0",
"kyverno@1.19.0", "kyverno@1.14.3",
"syft@1.51.0", "syft@1.29.0",
"grype@0.118.0", "grype@0.92.2",
"traefik@3.7.10", "traefik@3.6.7",
"claude-code@2.1.245", "claude-code@latest",
"go@latest", "go@latest",
"dotnet-sdk@8.0.424", "dotnet-sdk@latest",
"opentofu@1.12.5", "opentofu@1.11.6",
"_1password@2.30.0", "_1password@latest",
"github-cli@2.23.0", "github-cli@latest",
"upcloud-cli@3.36.0", "upcloud-cli@3.29.0",
"awscli2@2.35.11" "awscli2@2.34.24"
], ],
"shell": { "shell": {
"init_hook": [ "init_hook": [
+6
View File
@@ -1469,6 +1469,12 @@ ArgoCD will sync the Keycloak config, and the registrar CronJob will pick up the
| `k8s.secret.client-id-key` | No | `client-id` | Field name for the client ID in the K8s Secret | | `k8s.secret.client-id-key` | No | `client-id` | Field name for the client ID in the K8s Secret |
| `k8s.secret.client-secret-key` | No | `client-secret` | Field name for the client secret in the K8s Secret | | `k8s.secret.client-secret-key` | No | `client-secret` | Field name for the client secret in the K8s Secret |
#### Public CLI Client (Device-Code Login)
`forte-cli` is a shared **public** client (no secret) with the RFC 8628 device-authorization grant enabled (`oauth2.device.authorization.grant.enabled: "true"`, `standardFlowEnabled: false`, `directAccessGrantsEnabled: false`). Downloaded skills and CLI tools that log in through the Auth Sidecar (forte-drop first) use it with `<PREFIX>_CLIENT_ID=forte-cli`; nothing per-tool needs to be registered in Keycloak.
It must be defined in `forte-realm.json` (this legacy path): the self-service registrar hardcodes `publicClient: false` / `standardFlowEnabled: true` and drops `attributes`, so a `client-config` Secret cannot produce a public device-code client. It carries no `k8s.secret.sync` attribute (the registrar's secret sync skips it) and is listed in the cleanup CronJob's protected clients.
### Retrieving Secrets for External Deployments ### Retrieving Secrets for External Deployments
The registrar always writes a **central copy** of every synced secret to the `secrets` namespace, in addition to the target namespace. This allows operators to retrieve client credentials for applications deployed outside this cluster: The registrar always writes a **central copy** of every synced secret to the `secrets` namespace, in addition to the target namespace. This allows operators to retrieve client credentials for applications deployed outside this cluster:
@@ -17,7 +17,7 @@ spec:
source: source:
repoURL: https://charts.jetstack.io repoURL: https://charts.jetstack.io
chart: cert-manager chart: cert-manager
targetRevision: "v1.21.2" targetRevision: "v1.14.0"
helm: helm:
values: | values: |
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://fluent.github.io/helm-charts - repoURL: https://fluent.github.io/helm-charts
chart: fluent-bit chart: fluent-bit
targetRevision: 0.58.2 targetRevision: 0.47.10
helm: helm:
releaseName: fluent-bit releaseName: fluent-bit
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://dl.gitea.com/charts - repoURL: https://dl.gitea.com/charts
chart: actions chart: actions
targetRevision: "0.1.2" targetRevision: "0.0.5"
helm: helm:
releaseName: gitea-actions releaseName: gitea-actions
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://dl.gitea.com/charts - repoURL: https://dl.gitea.com/charts
chart: gitea chart: gitea
targetRevision: "12.7.0" targetRevision: "12.6.0"
helm: helm:
releaseName: gitea releaseName: gitea
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://grafana.github.io/helm-charts - repoURL: https://grafana.github.io/helm-charts
chart: grafana chart: grafana
targetRevision: "10.5.15" targetRevision: "8.0.0"
helm: helm:
releaseName: grafana releaseName: grafana
valueFiles: valueFiles:
+1 -1
View File
@@ -36,7 +36,7 @@ spec:
source: source:
chart: kyverno chart: kyverno
repoURL: https://kyverno.github.io/kyverno/ repoURL: https://kyverno.github.io/kyverno/
targetRevision: 3.9.1 targetRevision: v3.7.0 # Update to latest stable version
helm: helm:
releaseName: kyverno releaseName: kyverno
valuesObject: valuesObject:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://grafana.github.io/helm-charts - repoURL: https://grafana.github.io/helm-charts
chart: loki chart: loki
targetRevision: "7.3.0" targetRevision: "6.0.0"
helm: helm:
releaseName: loki releaseName: loki
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://opencost.github.io/opencost-helm-chart - repoURL: https://opencost.github.io/opencost-helm-chart
chart: opencost chart: opencost
targetRevision: "1.43.2" targetRevision: "1.42.0"
helm: helm:
releaseName: opencost releaseName: opencost
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://prometheus-community.github.io/helm-charts - repoURL: https://prometheus-community.github.io/helm-charts
chart: prometheus chart: prometheus
targetRevision: "28.16.0" targetRevision: "28.9.0"
helm: helm:
releaseName: prometheus releaseName: prometheus
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: ghcr.io/renovatebot/charts - repoURL: ghcr.io/renovatebot/charts
chart: renovate chart: renovate
targetRevision: "46.318.0" targetRevision: "46.109.0"
helm: helm:
releaseName: renovate releaseName: renovate
valueFiles: valueFiles:
+2 -2
View File
@@ -16,8 +16,8 @@ spec:
source: source:
chart: sealed-secrets chart: sealed-secrets
repoURL: https://bitnami.github.io/sealed-secrets repoURL: https://bitnami-labs.github.io/sealed-secrets
targetRevision: 2.20.0 targetRevision: 2.16.2 # Update to latest stable version
helm: helm:
releaseName: sealed-secrets releaseName: sealed-secrets
parameters: parameters:
@@ -24,7 +24,7 @@ spec:
sources: sources:
- repoURL: https://traefik.github.io/charts - repoURL: https://traefik.github.io/charts
chart: traefik chart: traefik
targetRevision: "28.3.0" targetRevision: "28.0.0"
helm: helm:
releaseName: traefik releaseName: traefik
valueFiles: valueFiles:
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://helm.releases.hashicorp.com - repoURL: https://helm.releases.hashicorp.com
chart: vault chart: vault
targetRevision: "0.34.1" targetRevision: "0.32.0"
helm: helm:
releaseName: vault releaseName: vault
valueFiles: valueFiles:
@@ -17,7 +17,7 @@ spec:
sources: sources:
- repoURL: https://guerzon.github.io/vaultwarden - repoURL: https://guerzon.github.io/vaultwarden
chart: vaultwarden chart: vaultwarden
targetRevision: "0.46.2" targetRevision: "0.36.4"
helm: helm:
releaseName: vaultwarden releaseName: vaultwarden
valueFiles: valueFiles:
+22 -12
View File
@@ -186,6 +186,21 @@ keycloakConfigCli:
} }
} }
] ]
},
{
"clientId": "forte-cli",
"name": "Forte CLI",
"description": "Shared public client for RFC 8628 device-code login from downloaded skills/CLI tools (forte-drop first) against services behind Auth Sidecar. No client secret.",
"enabled": true,
"protocol": "openid-connect",
"standardFlowEnabled": false,
"directAccessGrantsEnabled": false,
"publicClient": true,
"redirectUris": [],
"webOrigins": [],
"attributes": {
"oauth2.device.authorization.grant.enabled": "true"
}
} }
], ],
"browserFlow": "browser-auto-idp", "browserFlow": "browser-auto-idp",
@@ -290,7 +305,6 @@ extraDeploy:
namespace: keycloak namespace: keycloak
spec: spec:
schedule: "*/2 * * * *" schedule: "*/2 * * * *"
timeZone: "Europe/Oslo"
concurrencyPolicy: Forbid concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1 successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3 failedJobsHistoryLimit: 3
@@ -303,7 +317,7 @@ extraDeploy:
restartPolicy: Never restartPolicy: Never
containers: containers:
- name: registrar - name: registrar
image: alpine:3.24 image: alpine:3.20
command: [ "/bin/sh", "-c" ] command: [ "/bin/sh", "-c" ]
args: args:
- | - |
@@ -618,9 +632,7 @@ extraDeploy:
name: keycloak-client-cleanup name: keycloak-client-cleanup
namespace: keycloak namespace: keycloak
spec: spec:
schedule: "0 3 1 * *" schedule: "0 3 * * 0"
timeZone: "Europe/Oslo"
startingDeadlineSeconds: 3600
concurrencyPolicy: Forbid concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1 successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3 failedJobsHistoryLimit: 3
@@ -633,7 +645,7 @@ extraDeploy:
restartPolicy: Never restartPolicy: Never
containers: containers:
- name: cleanup - name: cleanup
image: alpine:3.24 image: alpine:3.20
command: [ "/bin/sh", "-c" ] command: [ "/bin/sh", "-c" ]
args: args:
- | - |
@@ -671,21 +683,19 @@ extraDeploy:
MIN_AGE_SEC=$((MIN_AGE_DAYS * 86400)) MIN_AGE_SEC=$((MIN_AGE_DAYS * 86400))
# Hardcoded protected clients (never delete these) # Hardcoded protected clients (never delete these)
PROTECTED_JSON='["gitea","grafana","argocd","vaultwarden","account","account-console","admin-cli","broker","realm-management","security-admin-console"]' PROTECTED_JSON='["gitea","grafana","argocd","forte-cli","vaultwarden","account","account-console","admin-cli","broker","realm-management","security-admin-console"]'
echo "Fetching clients from realm '${REALM}'..." echo "Fetching clients from realm '${REALM}'..."
CLIENTS=$(curl -sf -H "Authorization: Bearer ${TOKEN}" \ CLIENTS=$(curl -sf -H "Authorization: Bearer ${TOKEN}" \
"${KEYCLOAK_URL}/admin/realms/${REALM}/clients") "${KEYCLOAK_URL}/admin/realms/${REALM}/clients")
CANDIDATES=$(echo "$CLIENTS" | jq -c --argjson protected "$PROTECTED_JSON" \ CANDIDATES=$(echo "$CLIENTS" | jq -c --argjson protected "$PROTECTED_JSON" --argjson now "$NOW_SEC" --argjson min_age "$MIN_AGE_SEC" --arg pattern "$CLIENT_ID_PATTERN" '
--argjson now "$NOW_SEC" --argjson min_age "$MIN_AGE_SEC" --arg pattern "$CLIENT_ID_PATTERN" '
[ [
.[] .[]
| select(.clientId as $cid | $protected | index($cid) | not) | select(.clientId as $cid | $protected | index($cid) | not)
| select(.attributes["k8s.secret.sync"] != "true") | select(.attributes["k8s.secret.sync"] != "true")
| select(.clientId | test($pattern; "i")) | select(.clientId | test($pattern; "i"))
| select(.attributes["client.secret.creation.time"] != null) | select((.createdTimestamp // 0) / 1000 < ($now - $min_age))
| select((.attributes["client.secret.creation.time"] | tonumber) < ($now - $min_age))
] ]
') ')
@@ -733,7 +743,7 @@ extraDeploy:
- name: DRY_RUN - name: DRY_RUN
value: "false" value: "false"
- name: MIN_AGE_DAYS - name: MIN_AGE_DAYS
value: "60" value: "15"
volumeMounts: volumeMounts:
- name: keycloak-credentials - name: keycloak-credentials
mountPath: /secrets mountPath: /secrets
-9
View File
@@ -17,14 +17,7 @@ loki:
period: 24h period: 24h
object_store: filesystem # we're storing on filesystem so there's no real persistence here. object_store: filesystem # we're storing on filesystem so there's no real persistence here.
schema: v13 schema: v13
compactor:
working_directory: /var/loki/compactor
retention_enabled: true
delete_request_store: filesystem
compaction_interval: 10m
retention_delete_delay: 2h
limits_config: limits_config:
retention_period: 168h # 7 days
reject_old_samples: true reject_old_samples: true
reject_old_samples_max_age: 168h reject_old_samples_max_age: 168h
ingestion_rate_mb: 15 ingestion_rate_mb: 15
@@ -35,8 +28,6 @@ chunksCache:
resultsCache: resultsCache:
enabled: false enabled: false
singleBinary: singleBinary:
persistence:
size: 20Gi
replicas: 1 replicas: 1
resources: resources:
requests: requests:
-5
View File
@@ -21,11 +21,6 @@ renovate:
"assignees": ["danijel.simeunovic"], "assignees": ["danijel.simeunovic"],
"reviewers": ["danijel.simeunovic"] "reviewers": ["danijel.simeunovic"]
}, },
{
"matchRepositories": ["**/launchpad"],
"assignees": ["danijel.simeunovic"],
"reviewers": ["danijel.simeunovic"]
},
{ {
"matchRepositories": ["**/forte-helm"], "matchRepositories": ["**/forte-helm"],
"assignees": ["danijel.simeunovic"], "assignees": ["danijel.simeunovic"],
-67
View File
@@ -1,67 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
"group:allNonMajor",
":dependencyDashboard",
":semanticCommits"
],
"timezone": "Europe/Oslo",
"labels": ["renovate"],
"reviewers": ["danijel.simeunovic"],
"prConcurrentLimit": 10,
"prHourlyLimit": 4,
"minimumReleaseAge": "3 days",
"ignorePaths": [
"**/*-sealed.yaml",
"cluster-resources/policies/**",
"private/**",
".devbox/**"
],
"argocd": {
"description": "ArgoCD Applications live under infra/, apps/ and the root app-of-apps files. The manager skips any file without an argoproj.io apiVersion, so matching broadly is safe.",
"managerFilePatterns": [
"/^_app-of-apps-.+\\.yaml$/",
"/^apps/.+\\.yaml$/",
"/^infra/.+\\.yaml$/"
]
},
"helm-values": {
"description": "Values files are named <app>-values.yaml, not the default values.yaml.",
"managerFilePatterns": ["/^infra/values/.+\\.ya?ml$/"]
},
"kubernetes": {
"description": "Plain manifests with inline image references. Kyverno policies are excluded via ignorePaths - their images are Go templates, not tags.",
"managerFilePatterns": [
"/^cluster-resources/.+\\.yaml$/",
"/^apps/.+/resources/.+\\.yaml$/"
]
},
"packageRules": [
{
"description": "Every Application carries a second source pointing at this repo at HEAD for $values. HEAD is not a version.",
"matchDatasources": ["git-tags"],
"matchDepNames": ["/forteapps\\.net/"],
"enabled": false
},
{
"description": "Platform chart majors usually carry values-schema or CRD breaks - flag them for a careful read.",
"matchFileNames": ["infra/**"],
"matchUpdateTypes": ["major"],
"labels": ["renovate", "breaking-change"],
"minimumReleaseAge": "7 days"
},
{
"description": "Patch-level platform bumps are routine - let them through faster.",
"matchFileNames": ["infra/**"],
"matchUpdateTypes": ["patch"],
"minimumReleaseAge": "1 day"
}
]
}