diff --git a/.github/workflows/label-not-gittensor.yml b/.github/workflows/label-not-gittensor.yml new file mode 100644 index 000000000..7b846e8f7 --- /dev/null +++ b/.github/workflows/label-not-gittensor.yml @@ -0,0 +1,60 @@ +name: Label non-Gittensor PRs + +on: + pull_request_target: + types: + - opened + - reopened + +permissions: + pull-requests: write + +jobs: + label-pr: + runs-on: ubuntu-latest + steps: + - name: Add not-gittensor label for matched authors + uses: actions/github-script@v7 + env: + GITTENSOR_USERS: ${{ vars.GITTENSOR_USERS || '[]' }} + GITTENSOR_EXCEPTIONS: ${{ vars.GITTENSOR_EXCEPTIONS || '[]' }} + TARGET_LABEL: not-gittensor + with: + script: | + const parseList = (raw, name) => { + try { + const parsed = JSON.parse(raw || '[]'); + if (!Array.isArray(parsed)) { + core.setFailed(`${name} must be a JSON array.`); + return []; + } + return parsed.map((value) => String(value).toLowerCase()); + } catch (error) { + core.setFailed(`Failed to parse ${name}: ${error.message}`); + return []; + } + }; + + const author = context.payload.pull_request.user.login.toLowerCase(); + const users = new Set(parseList(process.env.GITTENSOR_USERS, 'GITTENSOR_USERS')); + const exceptions = new Set(parseList(process.env.GITTENSOR_EXCEPTIONS, 'GITTENSOR_EXCEPTIONS')); + + if (users.has(author) || exceptions.has(author)) { + core.info(`No label needed for @${author}.`); + return; + } + + const existingLabels = context.payload.pull_request.labels.map((label) => label.name); + if (existingLabels.includes(process.env.TARGET_LABEL)) { + core.info(`Label ${process.env.TARGET_LABEL} already present.`); + return; + } + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: [process.env.TARGET_LABEL], + }); + + core.info(`Added ${process.env.TARGET_LABEL} to PR #${context.payload.pull_request.number}.`); diff --git a/.sure-version b/.sure-version index 38d939e70..dafd26204 100644 --- a/.sure-version +++ b/.sure-version @@ -1 +1 @@ -0.7.1-alpha.10 +0.7.1-alpha.11 diff --git a/Dockerfile b/Dockerfile index 2cb2c83e7..c165b18f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ WORKDIR /rails # Install base packages RUN apt-get update -qq \ - && apt-get install --no-install-recommends -y curl libvips postgresql-client libyaml-0-2 procps \ + && apt-get install --no-install-recommends -y curl libvips postgresql-client libyaml-0-2 procps libjemalloc2 \ && rm -rf /var/lib/apt/lists /var/cache/apt/archives # Set production environment @@ -19,7 +19,7 @@ ENV RAILS_ENV="production" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development" \ BUILD_COMMIT_SHA=${BUILD_COMMIT_SHA} - + # Throw-away build stage to reduce size of final image FROM base AS build diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index b8041ad3d..f5e98ae41 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -4,13 +4,17 @@ class MessagesController < ApplicationController before_action :set_chat def create - @message = UserMessage.create!( + @message = UserMessage.new( chat: @chat, content: message_params[:content], ai_model: message_params[:ai_model].presence || Chat.default_model ) - redirect_to chat_path(@chat, thinking: true) + if @message.save + redirect_to chat_path(@chat, thinking: true) + else + redirect_to chat_path(@chat), alert: @message.errors.full_messages.to_sentence + end end private diff --git a/app/controllers/trades_controller.rb b/app/controllers/trades_controller.rb index e3a90121e..e3aed40db 100644 --- a/app/controllers/trades_controller.rb +++ b/app/controllers/trades_controller.rb @@ -35,7 +35,7 @@ class TradesController < ApplicationController format.turbo_stream { stream_redirect_back_or_to account_path(@account) } end else - render :new, status: :unprocessable_entity + render :new, status: :unprocessable_entity, formats: [ :html ] end end @@ -69,7 +69,7 @@ class TradesController < ApplicationController end end else - render :show, status: :unprocessable_entity + render :show, status: :unprocessable_entity, formats: [ :html ] end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d265734c6..ab88dcc15 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -27,21 +27,27 @@ class UsersController < ApplicationController end else was_ai_enabled = @user.ai_enabled - @user.update!(user_params.except(:redirect_to, :delete_profile_image)) - @user.profile_image.purge if should_purge_profile_image? + if @user.update(user_params.except(:redirect_to, :delete_profile_image)) + @user.profile_image.purge if should_purge_profile_image? - # Add a special notice if AI was just enabled or disabled - notice = if !was_ai_enabled && @user.ai_enabled - "AI Assistant has been enabled successfully." - elsif was_ai_enabled && !@user.ai_enabled - "AI Assistant has been disabled." + # Add a special notice if AI was just enabled or disabled + notice = if !was_ai_enabled && @user.ai_enabled + "AI Assistant has been enabled successfully." + elsif was_ai_enabled && !@user.ai_enabled + "AI Assistant has been disabled." + else + t(".success") + end + + respond_to do |format| + format.html { handle_redirect(notice) } + format.json { head :ok } + end else - t(".success") - end - - respond_to do |format| - format.html { handle_redirect(notice) } - format.json { head :ok } + respond_to do |format| + format.html { redirect_to settings_profile_path, alert: @user.errors.full_messages.to_sentence } + format.json { render json: { errors: @user.errors.full_messages }, status: :unprocessable_entity } + end end end end diff --git a/app/javascript/controllers/bank_search_controller.js b/app/javascript/controllers/bank_search_controller.js index a2c045cd9..155a7a8bb 100644 --- a/app/javascript/controllers/bank_search_controller.js +++ b/app/javascript/controllers/bank_search_controller.js @@ -7,9 +7,9 @@ export default class extends Controller { const query = this.inputTarget.value.toLocaleLowerCase().trim(); let visibleCount = 0; - this.itemTargets.forEach(item => { - const name = item.dataset.bankName?.toLocaleLowerCase() ?? ""; - const match = name.includes(query); + this.itemTargets.forEach((item) => { + const haystack = (item.dataset.bankSearch ?? "").toLocaleLowerCase(); + const match = haystack.includes(query); item.style.display = match ? "" : "none"; if (match) visibleCount++; }); diff --git a/app/models/account.rb b/app/models/account.rb index 5f9ad5e68..458f50bbe 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -2,7 +2,10 @@ class Account < ApplicationRecord include AASM, Syncable, Monetizable, Chartable, Linkable, Enrichable, Anchorable, Reconcileable, TaxTreatable before_validation :assign_default_owner, if: -> { owner_id.blank? } + before_destroy :capture_account_statement_ids_to_move + before_destroy :cleanup_transfers + after_destroy_commit :move_account_statements_to_inbox validates :name, :balance, :currency, presence: true @@ -561,4 +564,12 @@ class Account < ApplicationRecord updated_at: Time.current ) end + + def cleanup_transfers + transaction_ids = entries.where(entryable_type: "Transaction").pluck(:entryable_id) + + transfers = Transfer.where(inflow_transaction_id: transaction_ids).or(Transfer.where(outflow_transaction_id: transaction_ids)) + + transfers.find_each(&:destroy!) + end end diff --git a/app/models/transfer.rb b/app/models/transfer.rb index 878e899be..9b39d0f7d 100644 --- a/app/models/transfer.rb +++ b/app/models/transfer.rb @@ -38,8 +38,16 @@ class Transfer < ApplicationRecord # Once transfer is destroyed, we need to mark the denormalized kind fields on the transactions def destroy! Transfer.transaction do - inflow_transaction.update!(kind: "standard") - outflow_transaction.update!(kind: "standard") + [ inflow_transaction, outflow_transaction ].each do |transaction| + next if transaction.nil? + next unless Transaction.exists?(transaction.id) + begin + transaction.update!(kind: "standard") + rescue ActiveRecord::RecordNotFound + rescue NoMethodError + next + end + end super end end diff --git a/app/models/user.rb b/app/models/user.rb index b1c40bb76..74016d755 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -51,6 +51,7 @@ class User < ApplicationRecord validates :password, length: { minimum: 8 }, allow_nil: true normalizes :email, with: ->(email) { email.strip.downcase } normalizes :unconfirmed_email, with: ->(email) { email&.strip&.downcase } + normalizes :locale, with: ->(locale) { locale.presence } normalizes :first_name, :last_name, with: ->(value) { value.strip.presence } diff --git a/app/views/admin/users/index.html.erb b/app/views/admin/users/index.html.erb index c31a1fb61..5e5a0ec0a 100644 --- a/app/views/admin/users/index.html.erb +++ b/app/views/admin/users/index.html.erb @@ -12,7 +12,7 @@ <%= f.label :role, t(".filters.role"), class: "block text-sm font-medium text-primary mb-1" %> <%= f.select :role, options_for_select( - [[t(".filters.role_all"), ""], [t(".roles.guest"), "guest"], [t(".roles.member", default: "Member"), "member"], [t(".roles.admin"), "admin"], [t(".roles.super_admin"), "super_admin"]], + [[t(".filters.role_all"), ""], [t(".roles.guest"), "guest"], [t(".roles.member"), "member"], [t(".roles.admin"), "admin"], [t(".roles.super_admin"), "super_admin"]], params[:role] ), {}, @@ -75,7 +75,7 @@ <% elsif sub %> "> + <%= sub.active? ? "bg-success/10 text-success" : "bg-surface text-secondary" %>"> <%= sub.status.humanize %> <% else %> @@ -87,7 +87,7 @@
| <%= t(".table.user") %> | <%= t(".table.last_login") %> | @@ -123,7 +123,7 @@ <%= form.select :role, options_for_select([ [t(".roles.guest"), "guest"], - [t(".roles.member", default: "Member"), "member"], + [t(".roles.member"), "member"], [t(".roles.admin"), "admin"], [t(".roles.super_admin"), "super_admin"] ], user.role), @@ -139,7 +139,7 @@ <% if pending_invitations.any? %>
|---|---|
|
<%= icon "mail", class: "w-5 h-5 text-secondary shrink-0" %>
@@ -160,7 +160,7 @@
<% end %>
@@ -198,9 +198,9 @@
- <%= t(".roles.member", default: "Member") %>
+ <%= t(".roles.member") %>
-
<%= t(".role_descriptions.member", default: "Basic user access. Can manage their own accounts, transactions, and settings.") %> +<%= t(".role_descriptions.member") %>
@@ -209,7 +209,7 @@
<%= t(".role_descriptions.admin") %>
-
+
<%= t(".roles.super_admin") %>
<%= t(".role_descriptions.super_admin") %> diff --git a/app/views/enable_banking_items/select_bank.html.erb b/app/views/enable_banking_items/select_bank.html.erb index 124c8e3ec..095ae6738 100644 --- a/app/views/enable_banking_items/select_bank.html.erb +++ b/app/views/enable_banking_items/select_bank.html.erb @@ -28,7 +28,7 @@
<% @aspsps.each do |aspsp| %>
-
+
diff --git a/app/views/imports/new.html.erb b/app/views/imports/new.html.erb
index e71d84b6f..78950bd76 100644
--- a/app/views/imports/new.html.erb
+++ b/app/views/imports/new.html.erb
@@ -122,7 +122,7 @@
<%= render "imports/import_option",
type: "TransactionImport",
icon_name: "bar-chart-2",
- icon_bg_class: "bg-gray-tint-5",
+ icon_bg_class: "bg-surface-inset",
icon_text_class: "text-subdued",
label: t(".import_ynab"),
enabled: false,
diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint
index 67ef49314..672521a98 100755
--- a/bin/docker-entrypoint
+++ b/bin/docker-entrypoint
@@ -1,5 +1,15 @@
#!/bin/bash -e
+# Use jemalloc to reduce memory fragmentation if available
+JEMALLOC="/usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2"
+if [ -f "$JEMALLOC" ] && [ -z "${DISABLE_JEMALLOC}" ]; then
+ export LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$JEMALLOC"
+else
+ [ -n "${DISABLE_JEMALLOC}" ] \
+ && echo "WARNING: jemalloc disabled via DISABLE_JEMALLOC" \
+ || echo "WARNING: jemalloc not found at $JEMALLOC, skipping"
+fi
+
# If running the rails server then create or migrate existing database
if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then
./bin/rails db:prepare
diff --git a/charts/sure/CHANGELOG.md b/charts/sure/CHANGELOG.md
index 0abee238d..490cbe136 100644
--- a/charts/sure/CHANGELOG.md
+++ b/charts/sure/CHANGELOG.md
@@ -5,16 +5,22 @@ All notable changes to the Sure Helm chart will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [Unreleased]
+## [0.7.1] - 2026-05-31]
### Changed
-- Bumped `pipelock.image.tag` from `2.0.0` to `2.2.0` (three minor releases behind latest). Floating `@v2` CI action pin picks up patch/minor updates automatically.
-- Refreshed pipelock feature notes in the chart README, `docs/hosting/pipelock.md`, and `pipelock.example.yaml` to reference the upstream changelog instead of a single version.
+- Bumped `pipelock.image.tag` from `2.2.0` to `2.5.0`. Picks up three releases of scanner, federation, and audit work — see the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/blob/main/CHANGELOG.md) for the full surface.
+- Refreshed pipelock feature notes in the chart README, `docs/hosting/pipelock.md`, and `pipelock.example.yaml` to call out 2.5 highlights (Audit Packet v0, request-body prompt-injection blocking, SPIFFE-strict inbound envelopes, scanner attribution on MCP block receipts).
+- Expanded the `pipelock.extraConfig` escape-hatch comment to reference the new sections available in 2.5 (browser_shield, mediation_envelope, redaction, learn, media_policy, a2a_scanning, emit).
+- Defaulted `pipelock.mcpToolPolicy.enabled` to `false`. Pipelock 2.x rejects an enabled `mcp_tool_policy` with no rules, so the prior chart default (`enabled: true`, empty rules) hard-failed config validation on startup. Operators who want tool policy active must now set `enabled: true` and provide at least one entry in `pipelock.mcpToolPolicy.rules`.
### Added
+- `pipelock.requestBodyScanning` (pipelock 2.5+): structured config for scanning outbound request bodies for prompt-injection and bodies/sensitive headers for DLP payloads. Disabled by default to preserve existing chart behavior; opt in with `enabled: true`.
+- `pipelock.healthWatchdog` (pipelock 2.4+): structured config for the wedge-detection watchdog. Operators can opt into per-subsystem detail in `/health` responses via `exposeSubsystems: true`.
+- `pipelock.mcpToolPolicy.rules`: structured Helm values for rendering `mcp_tool_policy.rules`, including redirect-profile references.
+- `asserts.tpl` guard that fails `helm template`/`helm install` when `pipelock.mcpToolPolicy.enabled=true` is paired with an empty `rules` list, surfacing the pipelock validation error at render time instead of container startup.
- README: CI scan status badge for the pipelock workflow.
-## [0.6.9-alpha] - 2026-03-24
+## [0.6.9] - 2026-03-31
### Changed
- Bumped `pipelock.image.tag` from `1.5.0` to `2.0.0`
@@ -58,7 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Renamed `_asserts.tpl` to `asserts.tpl` — Helm's `_` prefix convention prevented guards from executing
-## [0.6.7-alpha] - 2026-01-10
+## [0.6.7] - 2026-01-31
### Added
- **Redis Sentinel support for Sidekiq high availability**: Application now automatically detects and configures Sidekiq to use Redis Sentinel when `redisOperator.mode=sentinel` and `redisOperator.sentinel.enabled=true`
diff --git a/charts/sure/Chart.yaml b/charts/sure/Chart.yaml
index 412a3c29e..7101091a8 100644
--- a/charts/sure/Chart.yaml
+++ b/charts/sure/Chart.yaml
@@ -2,8 +2,8 @@ apiVersion: v2
name: sure
description: Official Helm chart for deploying the Sure Rails app (web + Sidekiq) on Kubernetes with optional HA PostgreSQL (CloudNativePG) and Redis.
type: application
-version: 0.7.1-alpha.10
-appVersion: "0.7.1-alpha.10"
+version: 0.7.1-alpha.11
+appVersion: "0.7.1-alpha.11"
kubeVersion: ">=1.25.0-0"
diff --git a/charts/sure/README.md b/charts/sure/README.md
index 73d5eb464..42a6688c8 100644
--- a/charts/sure/README.md
+++ b/charts/sure/README.md
@@ -645,7 +645,7 @@ hpa:
- **Forward proxy** (port 8888): Scans outbound HTTPS from Faraday-based AI clients. Auto-injected via `HTTPS_PROXY` env vars when enabled.
- **MCP reverse proxy** (port 8889): Scans inbound MCP traffic from external AI assistants.
-Recent pipelock releases add enhanced tool poisoning detection (full JSON schema scanning), per-read kill switch preemption, trusted domain allowlisting, MCP tool redirect profiles, signed action receipts, per-pattern DLP warn mode, and the `pipelock posture verify` / `pipelock session` CLIs. Process sandboxing and attack simulation are also available via `extraConfig` and CLI. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
+Recent pipelock releases add the Audit Packet v0 schema and language-portable verifiers (Go, TypeScript, Rust), request-body prompt-injection blocking, SPIFFE-strict inbound mediation envelopes, scanner attribution on MCP block receipts, enhanced tool poisoning detection, per-read kill switch preemption, trusted domain allowlisting, MCP tool redirect profiles, signed action receipts, per-pattern DLP warn mode, learn-and-lock behavioural contracts, the wedge-detection health watchdog, and the `pipelock posture verify` / `pipelock session` / `pipelock doctor` CLIs. Browser Shield, process sandboxing, and attack simulation are available via `extraConfig` and CLI. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
### Enabling Pipelock
@@ -653,7 +653,7 @@ Recent pipelock releases add enhanced tool poisoning detection (full JSON schema
pipelock:
enabled: true
image:
- tag: "2.2.0"
+ tag: "2.5.0"
mode: balanced # strict, balanced, or audit
```
@@ -677,12 +677,45 @@ pipelock:
mcpToolPolicy:
enabled: true
action: redirect # or use per-rule action overrides
+ rules:
+ - name: redirect-fetch
+ toolPattern: "^(fetch|web_fetch)$"
+ action: redirect
+ redirectProfile: safe-fetch
redirectProfiles:
safe-fetch:
exec: ["/pipelock", "internal-redirect", "fetch-proxy"]
reason: "Route fetch calls through audited proxy"
```
+### Request body scanning (pipelock 2.5+)
+
+Pipelock 2.5 added prompt-injection detection on outbound request bodies (JSON, form-encoded, raw text, WebSocket frames). When enabled, findings hard-block non-provider destinations even when `action: warn`; trusted provider hosts (OpenAI, Anthropic, etc.) remain exempt through the response-scanning exemption list.
+
+```yaml
+pipelock:
+ requestBodyScanning:
+ enabled: true
+ action: warn # warn or block
+ maxBodyBytes: 5242880 # 5 MB; fail-closed above this
+ scanHeaders: true
+ headerMode: sensitive # "sensitive" or "all"
+```
+
+Disabled by default. Roll out with `action: warn` first to observe findings in logs without blocking, then flip to `action: block` once the false-positive rate is acceptable.
+
+### Health watchdog
+
+The wedge-detection watchdog returns 503 on `/health` when a subsystem heartbeat (proxy hot path, MCP listener, rules-engine reload watcher) goes stale. Enabled by default in pipelock; the chart exposes the controls so operators can opt into per-subsystem detail in the health payload:
+
+```yaml
+pipelock:
+ healthWatchdog:
+ enabled: true
+ intervalSeconds: 2
+ exposeSubsystems: true # adds per-subsystem boolean map to /health
+```
+
### Validating your config
Pipelock includes CLI tools for config validation:
@@ -693,6 +726,9 @@ pipelock simulate --config pipelock.yaml
# Score your config's security posture (0-100)
pipelock audit score --config pipelock.yaml
+
+# Report whether configured protections are actually enforceable
+pipelock doctor
```
### Exposing MCP to external AI assistants
@@ -811,7 +847,7 @@ See `values.yaml` for the complete configuration surface, including:
- `migrations.*`: strategy job or initContainer
- `simplefin.encryption.*`: enable + backfill options
- `cronjobs.*`: custom CronJobs
-- `pipelock.*`: AI agent security proxy (forward proxy, MCP reverse proxy, DLP, injection scanning, trusted domains, tool redirect profiles, logging, serviceMonitor, ingress, PDB, extraConfig)
+- `pipelock.*`: AI agent security proxy (forward proxy, MCP reverse proxy, DLP, injection scanning, request-body scanning, health watchdog, trusted domains, tool redirect profiles, logging, serviceMonitor, ingress, PDB, extraConfig)
- `service.*`, `ingress.*`, `serviceMonitor.*`, `hpa.*`
## Helm tests
diff --git a/charts/sure/templates/asserts.tpl b/charts/sure/templates/asserts.tpl
index 1d481c0e9..52b3af9ac 100644
--- a/charts/sure/templates/asserts.tpl
+++ b/charts/sure/templates/asserts.tpl
@@ -21,3 +21,18 @@ Mutual exclusivity and configuration guards
{{- if and $extEnabled (not $plEnabled) $requirePL -}}
{{- fail "pipelock.requireForExternalAssistant is true but pipelock.enabled is false. Enable pipelock (pipelock.enabled=true) when using rails.externalAssistant, or set pipelock.requireForExternalAssistant=false." -}}
{{- end -}}
+
+{{/*
+Pipelock 2.x rejects an enabled mcp_tool_policy with no rules; surface this
+at helm template time instead of waiting for the container to crash-loop.
+*/}}
+{{- if $plEnabled -}}
+{{- $mtp := .Values.pipelock.mcpToolPolicy | default (dict) -}}
+{{- if hasKey $mtp "enabled" -}}
+{{- if $mtp.enabled -}}
+{{- if eq (len ($mtp.rules | default (list))) 0 -}}
+{{- fail "pipelock.mcpToolPolicy.enabled=true requires at least one entry in pipelock.mcpToolPolicy.rules. Pipelock rejects an enabled tool policy with no rules." -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
diff --git a/charts/sure/templates/pipelock-configmap.yaml b/charts/sure/templates/pipelock-configmap.yaml
index b9c8fa5b7..c77ee68ba 100644
--- a/charts/sure/templates/pipelock-configmap.yaml
+++ b/charts/sure/templates/pipelock-configmap.yaml
@@ -65,6 +65,34 @@
{{- $chainWindow = int (.Values.pipelock.toolChainDetection.windowSize | default 20) -}}
{{- $chainGap = int (.Values.pipelock.toolChainDetection.maxGap | default 3) -}}
{{- end -}}
+{{- $rbsEnabled := false -}}
+{{- $rbsAction := "warn" -}}
+{{- $rbsMaxBytes := 5242880 -}}
+{{- $rbsScanHeaders := true -}}
+{{- $rbsHeaderMode := "sensitive" -}}
+{{- if .Values.pipelock.requestBodyScanning -}}
+{{- if hasKey .Values.pipelock.requestBodyScanning "enabled" -}}
+{{- $rbsEnabled = .Values.pipelock.requestBodyScanning.enabled -}}
+{{- end -}}
+{{- $rbsAction = .Values.pipelock.requestBodyScanning.action | default "warn" -}}
+{{- $rbsMaxBytes = int (.Values.pipelock.requestBodyScanning.maxBodyBytes | default 5242880) -}}
+{{- if hasKey .Values.pipelock.requestBodyScanning "scanHeaders" -}}
+{{- $rbsScanHeaders = .Values.pipelock.requestBodyScanning.scanHeaders -}}
+{{- end -}}
+{{- $rbsHeaderMode = .Values.pipelock.requestBodyScanning.headerMode | default "sensitive" -}}
+{{- end -}}
+{{- $hwEnabled := true -}}
+{{- $hwInterval := 2 -}}
+{{- $hwExpose := false -}}
+{{- if .Values.pipelock.healthWatchdog -}}
+{{- if hasKey .Values.pipelock.healthWatchdog "enabled" -}}
+{{- $hwEnabled = .Values.pipelock.healthWatchdog.enabled -}}
+{{- end -}}
+{{- $hwInterval = int (.Values.pipelock.healthWatchdog.intervalSeconds | default 2) -}}
+{{- if hasKey .Values.pipelock.healthWatchdog "exposeSubsystems" -}}
+{{- $hwExpose = .Values.pipelock.healthWatchdog.exposeSubsystems -}}
+{{- end -}}
+{{- end -}}
{{- $logFormat := "json" -}}
{{- $logOutput := "stdout" -}}
{{- $logIncludeAllowed := false -}}
@@ -128,6 +156,25 @@ data:
mcp_tool_policy:
enabled: {{ $mcpPolicyEnabled }}
action: {{ $mcpPolicyAction }}
+{{- if and .Values.pipelock.mcpToolPolicy .Values.pipelock.mcpToolPolicy.rules }}
+ rules:
+{{- range .Values.pipelock.mcpToolPolicy.rules }}
+ - name: {{ required "pipelock.mcpToolPolicy.rules[].name is required" .name | quote }}
+ tool_pattern: {{ required "pipelock.mcpToolPolicy.rules[].toolPattern is required" .toolPattern | quote }}
+{{- if .argPattern }}
+ arg_pattern: {{ .argPattern | quote }}
+{{- end }}
+{{- if .argKey }}
+ arg_key: {{ .argKey | quote }}
+{{- end }}
+{{- if .action }}
+ action: {{ .action | quote }}
+{{- end }}
+{{- if .redirectProfile }}
+ redirect_profile: {{ .redirectProfile | quote }}
+{{- end }}
+{{- end }}
+{{- end }}
{{- if and .Values.pipelock.mcpToolPolicy .Values.pipelock.mcpToolPolicy.redirectProfiles }}
redirect_profiles:
{{- toYaml .Values.pipelock.mcpToolPolicy.redirectProfiles | nindent 8 }}
@@ -140,6 +187,16 @@ data:
action: {{ $chainAction }}
window_size: {{ $chainWindow }}
max_gap: {{ $chainGap }}
+ request_body_scanning:
+ enabled: {{ $rbsEnabled }}
+ action: {{ $rbsAction }}
+ max_body_bytes: {{ $rbsMaxBytes }}
+ scan_headers: {{ $rbsScanHeaders }}
+ header_mode: {{ $rbsHeaderMode }}
+ health_watchdog:
+ enabled: {{ $hwEnabled }}
+ interval_seconds: {{ $hwInterval }}
+ expose_subsystems: {{ $hwExpose }}
logging:
format: {{ $logFormat }}
output: {{ $logOutput }}
diff --git a/charts/sure/values.yaml b/charts/sure/values.yaml
index f4b54f69e..d01d0dc5e 100644
--- a/charts/sure/values.yaml
+++ b/charts/sure/values.yaml
@@ -497,7 +497,7 @@ pipelock:
enabled: false
image:
repository: ghcr.io/luckypipewrench/pipelock
- tag: "2.2.0"
+ tag: "2.5.0"
pullPolicy: IfNotPresent
imagePullSecrets: []
replicas: 1
@@ -530,8 +530,17 @@ pipelock:
originPolicy: rewrite # rewrite, forward, or strip
# MCP tool policy: pre-execution rules for tool calls (shell obfuscation, etc.)
mcpToolPolicy:
- enabled: true
+ # Enable only when at least one rule is configured; pipelock rejects an
+ # enabled mcp_tool_policy with no rules.
+ enabled: false
action: warn
+ # Example:
+ # rules:
+ # - name: redirect-fetch
+ # toolPattern: "^(fetch|web_fetch)$"
+ # action: redirect
+ # redirectProfile: safe-fetch
+ rules: []
# Redirect profiles: route matched tool calls to audited handler programs instead
# of blocking. The handler returns a synthetic MCP response. Fail-closed on error.
# Example:
@@ -550,6 +559,24 @@ pipelock:
action: warn
windowSize: 20
maxGap: 3
+ # Request body scanning (pipelock 2.5+): detect prompt-injection payloads
+ # in outbound request bodies (JSON, form-encoded, raw text, WebSocket frames).
+ # In enforce mode, prompt-injection findings hard-block non-provider
+ # destinations even when action is "warn"; trusted provider hosts (OpenAI,
+ # Anthropic, etc.) remain exempt via the response_scanning exemption list.
+ requestBodyScanning:
+ enabled: false
+ action: warn # warn or block
+ maxBodyBytes: 5242880 # 5 MB; fail-closed above this
+ scanHeaders: true # scan request headers for DLP
+ headerMode: sensitive # "sensitive" or "all"
+ # Health watchdog (pipelock 2.4+): /health returns 503 when any subsystem
+ # heartbeat goes stale. Enabled by default in pipelock; exposed here so
+ # operators can opt into per-subsystem detail in the health payload.
+ healthWatchdog:
+ enabled: true
+ intervalSeconds: 2
+ exposeSubsystems: false # include per-subsystem map in /health response
service:
type: ClusterIP
resources:
@@ -601,8 +628,10 @@ pipelock:
includeBlocked: true
# Escape hatch: ADDITIONAL config sections appended to pipelock.yaml.
- # Use for sections not covered by structured values above (session_profiling,
- # data_budget, adaptive_enforcement, kill_switch, sandbox, reverse_proxy, etc.)
+ # Use for sections not covered by structured values above. Examples:
+ # session_profiling, data_budget, adaptive_enforcement, kill_switch, sandbox,
+ # reverse_proxy, redaction, browser_shield, mediation_envelope, learn,
+ # media_policy, a2a_scanning, emit (OTel agent.threat.detection attributes).
# Do NOT duplicate keys already rendered above - behavior is parser-dependent.
extraConfig: {}
diff --git a/compose.example.ai.yml b/compose.example.ai.yml
index 7c79178f7..48a696f38 100644
--- a/compose.example.ai.yml
+++ b/compose.example.ai.yml
@@ -112,7 +112,7 @@ x-rails-env: &rails_env
services:
pipelock:
- image: ghcr.io/luckypipewrench/pipelock:latest # pin to a specific version (e.g., :2.2.0) for production
+ image: ghcr.io/luckypipewrench/pipelock:latest # pin to a specific version (e.g., :2.5.0) for production
container_name: pipelock
hostname: pipelock
restart: unless-stopped
diff --git a/config/locales/views/imports/de.yml b/config/locales/views/imports/de.yml
index bd733bc77..faab67cc0 100644
--- a/config/locales/views/imports/de.yml
+++ b/config/locales/views/imports/de.yml
@@ -61,13 +61,13 @@ de:
rows_label: Zeilen
unassigned_account: Neues Konto für nicht zugewiesene Zeilen erstellen?
show:
- account_mapping_description: Weise alle Konten aus deiner importierten Datei den bestehenden Konten in %{product} zu. Du kannst auch neue Konten hinzufügen oder sie ohne Kategorie lassen.
+ account_mapping_description: Weise alle Konten aus deiner importierten Datei den bestehenden Konten in %{product_name} zu. Du kannst auch neue Konten hinzufügen oder sie ohne Kategorie lassen.
account_mapping_title: Konten zuweisen
- account_type_mapping_description: Weise alle Kontotypen aus deiner importierten Datei den Kontotypen in %{product} zu.
+ account_type_mapping_description: Weise alle Kontotypen aus deiner importierten Datei den Kontotypen in %{product_name} zu.
account_type_mapping_title: Kontotypen zuweisen
- category_mapping_description: Weise alle Kategorien aus deiner importierten Datei den bestehenden Kategorien in %{product} zu. Du kannst auch neue Kategorien hinzufügen oder sie ohne Kategorie lassen.
+ category_mapping_description: Weise alle Kategorien aus deiner importierten Datei den bestehenden Kategorien in %{product_name} zu. Du kannst auch neue Kategorien hinzufügen oder sie ohne Kategorie lassen.
category_mapping_title: Kategorien zuweisen
- tag_mapping_description: Weise alle Tags aus deiner importierten Datei den bestehenden Tags in %{product} zu. Du kannst auch neue Tags hinzufügen oder sie ohne Kategorie lassen.
+ tag_mapping_description: Weise alle Tags aus deiner importierten Datei den bestehenden Tags in %{product_name} zu. Du kannst auch neue Tags hinzufügen oder sie ohne Kategorie lassen.
tag_mapping_title: Tags zuweisen
uploads:
show:
diff --git a/config/locales/views/imports/en.yml b/config/locales/views/imports/en.yml
index 270b7d2f6..d97b7cf21 100644
--- a/config/locales/views/imports/en.yml
+++ b/config/locales/views/imports/en.yml
@@ -155,17 +155,17 @@ en:
show:
invalid_data: "You have invalid data, please edit until all errors are resolved"
account_mapping_description: Assign all of your imported file's accounts to
- Maybe's existing accounts. You can also add new accounts or leave them
+ %{product_name}'s existing accounts. You can also add new accounts or leave them
uncategorized.
account_mapping_title: Assign your accounts
account_type_mapping_description: Assign all of your imported file's account
- types to Maybe's
+ types to %{product_name}'s
account_type_mapping_title: Assign your account types
category_mapping_description: Assign all of your imported file's categories
- to Maybe's existing categories. You can also add new categories or leave
+ to %{product_name}'s existing categories. You can also add new categories or leave
them uncategorized.
category_mapping_title: Assign your categories
- tag_mapping_description: Assign all of your imported file's tags to Maybe's
+ tag_mapping_description: Assign all of your imported file's tags to %{product_name}'s
existing tags. You can also add new tags or leave them uncategorized.
tag_mapping_title: Assign your tags
uploads:
diff --git a/config/locales/views/imports/es.yml b/config/locales/views/imports/es.yml
index b8f0c9ca5..d42aa010d 100644
--- a/config/locales/views/imports/es.yml
+++ b/config/locales/views/imports/es.yml
@@ -61,13 +61,13 @@ es:
rows_label: Filas
unassigned_account: ¿Necesitas crear una nueva cuenta para las filas sin asignar?
show:
- account_mapping_description: Asigna todas las cuentas de tu archivo importado a las cuentas existentes de Sure. También puedes añadir nuevas cuentas o dejarlas sin categorizar.
+ account_mapping_description: Asigna todas las cuentas de tu archivo importado a las cuentas existentes de %{product_name}. También puedes añadir nuevas cuentas o dejarlas sin categorizar.
account_mapping_title: Asigna tus cuentas
- account_type_mapping_description: Asigna todos los tipos de cuenta de tu archivo importado a los de Sure.
+ account_type_mapping_description: Asigna todos los tipos de cuenta de tu archivo importado a los de %{product_name}.
account_type_mapping_title: Asigna tus tipos de cuenta
- category_mapping_description: Asigna todas las categorías de tu archivo importado a las categorías existentes de Sure. También puedes añadir nuevas categorías o dejarlas sin categorizar.
+ category_mapping_description: Asigna todas las categorías de tu archivo importado a las categorías existentes de %{product_name}. También puedes añadir nuevas categorías o dejarlas sin categorizar.
category_mapping_title: Asigna tus categorías
- tag_mapping_description: Asigna todas las etiquetas de tu archivo importado a las etiquetas existentes de Sure. También puedes añadir nuevas etiquetas o dejarlas sin categorizar.
+ tag_mapping_description: Asigna todas las etiquetas de tu archivo importado a las etiquetas existentes de %{product_name}. También puedes añadir nuevas etiquetas o dejarlas sin categorizar.
tag_mapping_title: Asigna tus etiquetas
uploads:
show:
diff --git a/config/locales/views/imports/hu.yml b/config/locales/views/imports/hu.yml
index 8221e18fe..543194625 100644
--- a/config/locales/views/imports/hu.yml
+++ b/config/locales/views/imports/hu.yml
@@ -134,13 +134,13 @@ hu:
next: Tovább
show:
invalid_data: "Érvénytelen adatok találhatók, kérjük szerkeszd, amíg minden hibát ki nem javítasz"
- account_mapping_description: Rendeld hozzá az importált fájl számláit a Maybe meglévő számláihoz. Új számlákat is hozzáadhatsz, vagy hagyhatod őket kategorizálatlanul.
+ account_mapping_description: Rendeld hozzá az importált fájl számláit a %{product_name} meglévő számláihoz. Új számlákat is hozzáadhatsz, vagy hagyhatod őket kategorizálatlanul.
account_mapping_title: Számlák hozzárendelése
- account_type_mapping_description: Rendeld hozzá az importált fájl számlatípusait a Maybe típusaihoz.
+ account_type_mapping_description: Rendeld hozzá az importált fájl számlatípusait a %{product_name} típusaihoz.
account_type_mapping_title: Számlatípusok hozzárendelése
- category_mapping_description: Rendeld hozzá az importált fájl kategóriáit a Maybe meglévő kategóriáihoz. Új kategóriákat is hozzáadhatsz, vagy hagyhatod őket kategorizálatlanul.
+ category_mapping_description: Rendeld hozzá az importált fájl kategóriáit a %{product_name} meglévő kategóriáihoz. Új kategóriákat is hozzáadhatsz, vagy hagyhatod őket kategorizálatlanul.
category_mapping_title: Kategóriák hozzárendelése
- tag_mapping_description: Rendeld hozzá az importált fájl címkéit a Maybe meglévő címkéihez. Új címkéket is hozzáadhatsz, vagy hagyhatod őket kategorizálatlanul.
+ tag_mapping_description: Rendeld hozzá az importált fájl címkéit a %{product_name} meglévő címkéihez. Új címkéket is hozzáadhatsz, vagy hagyhatod őket kategorizálatlanul.
tag_mapping_title: Címkék hozzárendelése
uploads:
update:
diff --git a/config/locales/views/imports/nb.yml b/config/locales/views/imports/nb.yml
index cebd1ddb0..3e4f60610 100644
--- a/config/locales/views/imports/nb.yml
+++ b/config/locales/views/imports/nb.yml
@@ -31,18 +31,18 @@ nb:
unassigned_account: Trenger å opprette en ny konto for utilordnede rader?
show:
account_mapping_description: Tilordne alle kontoene i den importerte filen din til
- Maybes eksisterende kontoer. Du kan også legge til nye kontoer eller la dem
+ %{product_name}s eksisterende kontoer. Du kan også legge til nye kontoer eller la dem
være ukategorisert.
account_mapping_title: Tilordne kontoene dine
account_type_mapping_description: Tilordne alle kontotypene i den importerte filen din til
- Maybes
+ %{product_name}s
account_type_mapping_title: Tilordne kontotypene dine
category_mapping_description: Tilordne alle kategoriene i den importerte filen din til
- Maybes eksisterende kategorier. Du kan også legge til nye kategorier eller la dem
+ %{product_name}s eksisterende kategorier. Du kan også legge til nye kategorier eller la dem
være ukategorisert.
category_mapping_title: Tilordne kategoriene dine
tag_mapping_description: Tilordne alle tagene i den importerte filen din til
- Maybes eksisterende tagger. Du kan også legge til nye tagger eller la dem
+ %{product_name}s eksisterende tagger. Du kan også legge til nye tagger eller la dem
være ukategorisert.
tag_mapping_title: Tilordne tagene dine
uploads:
diff --git a/config/locales/views/imports/nl.yml b/config/locales/views/imports/nl.yml
index 3d40a4e90..31a2d3678 100644
--- a/config/locales/views/imports/nl.yml
+++ b/config/locales/views/imports/nl.yml
@@ -37,13 +37,13 @@ nl:
rows_label: Rijen
unassigned_account: Moet u een nieuw account aanmaken voor niet-toegewezen rijen?
show:
- account_mapping_description: Wijs alle accounts van uw geïmporteerde bestand toe aan bestaande %{product} accounts. U kunt ook nieuwe accounts toevoegen of ze ongecategoriseerd laten.
+ account_mapping_description: Wijs alle accounts van uw geïmporteerde bestand toe aan bestaande %{product_name} accounts. U kunt ook nieuwe accounts toevoegen of ze ongecategoriseerd laten.
account_mapping_title: Uw accounts toewijzen
- account_type_mapping_description: Wijs alle accounttypen van uw geïmporteerde bestand toe aan %{product} accounttypen
+ account_type_mapping_description: Wijs alle accounttypen van uw geïmporteerde bestand toe aan %{product_name} accounttypen
account_type_mapping_title: Uw accounttypen toewijzen
- category_mapping_description: Wijs alle categorieën van uw geïmporteerde bestand toe aan bestaande %{product} categorieën. U kunt ook nieuwe categorieën toevoegen of ze ongecategoriseerd laten.
+ category_mapping_description: Wijs alle categorieën van uw geïmporteerde bestand toe aan bestaande %{product_name} categorieën. U kunt ook nieuwe categorieën toevoegen of ze ongecategoriseerd laten.
category_mapping_title: Uw categorieën toewijzen
- tag_mapping_description: Wijs alle tags van uw geïmporteerde bestand toe aan bestaande %{product} tags. U kunt ook nieuwe tags toevoegen of ze ongecategoriseerd laten.
+ tag_mapping_description: Wijs alle tags van uw geïmporteerde bestand toe aan bestaande %{product_name} tags. U kunt ook nieuwe tags toevoegen of ze ongecategoriseerd laten.
tag_mapping_title: Uw tags toewijzen
uploads:
show:
diff --git a/config/locales/views/imports/pl.yml b/config/locales/views/imports/pl.yml
index af8db190c..d5d1cd967 100644
--- a/config/locales/views/imports/pl.yml
+++ b/config/locales/views/imports/pl.yml
@@ -74,13 +74,13 @@ pl:
rows_label: Wiersze
unassigned_account: Chcesz utworzyć nowe konto dla nieprzypisanych wierszy?
show:
- account_mapping_description: Przypisz wszystkie konta z importowanego pliku do istniejących kont %{product}. Możesz też dodać nowe konta lub zostawić je bez przypisania.
+ account_mapping_description: Przypisz wszystkie konta z importowanego pliku do istniejących kont %{product_name}. Możesz też dodać nowe konta lub zostawić je bez przypisania.
account_mapping_title: Przypisz konta
- account_type_mapping_description: Przypisz wszystkie typy kont z importowanego pliku do typów używanych w %{product}.
+ account_type_mapping_description: Przypisz wszystkie typy kont z importowanego pliku do typów używanych w %{product_name}.
account_type_mapping_title: Przypisz typy kont
- category_mapping_description: Przypisz wszystkie kategorie z importowanego pliku do istniejących kategorii %{product}. Możesz też dodać nowe kategorie lub zostawić je bez przypisania.
+ category_mapping_description: Przypisz wszystkie kategorie z importowanego pliku do istniejących kategorii %{product_name}. Możesz też dodać nowe kategorie lub zostawić je bez przypisania.
category_mapping_title: Przypisz kategorie
- tag_mapping_description: Przypisz wszystkie tagi z importowanego pliku do istniejących tagów %{product}. Możesz też dodać nowe tagi lub zostawić je bez przypisania.
+ tag_mapping_description: Przypisz wszystkie tagi z importowanego pliku do istniejących tagów %{product_name}. Możesz też dodać nowe tagi lub zostawić je bez przypisania.
tag_mapping_title: Przypisz tagi
uploads:
show:
diff --git a/config/locales/views/imports/pt-BR.yml b/config/locales/views/imports/pt-BR.yml
index 15b71dc0e..84edb7b83 100644
--- a/config/locales/views/imports/pt-BR.yml
+++ b/config/locales/views/imports/pt-BR.yml
@@ -36,18 +36,18 @@ pt-BR:
unassigned_account: Precisa criar uma nova conta para linhas não atribuídas?
show:
account_mapping_description: Atribua todas as contas do seu arquivo importado às
- contas existentes no %{product}. Você também pode adicionar novas contas ou deixá-las
+ contas existentes no %{product_name}. Você também pode adicionar novas contas ou deixá-las
sem categoria.
account_mapping_title: Atribuir suas contas
account_type_mapping_description: Atribuir todos os tipos de conta do seu arquivo importado aos
- do %{product}
+ do %{product_name}
account_type_mapping_title: Atribuir seus tipos de conta
category_mapping_description: Atribua todas as categorias do seu arquivo importado às
- categorias existentes no %{product}. Você também pode adicionar novas categorias ou deixá-las
+ categorias existentes no %{product_name}. Você também pode adicionar novas categorias ou deixá-las
sem categoria.
category_mapping_title: Atribuir suas categorias
tag_mapping_description: Atribua todas as tags do seu arquivo importado às
- tags existentes no %{product}. Você também pode adicionar novas tags ou deixá-las
+ tags existentes no %{product_name}. Você também pode adicionar novas tags ou deixá-las
sem categoria.
tag_mapping_title: Atribuir suas tags
uploads:
diff --git a/config/locales/views/imports/ro.yml b/config/locales/views/imports/ro.yml
index bec1cf695..b9783f815 100644
--- a/config/locales/views/imports/ro.yml
+++ b/config/locales/views/imports/ro.yml
@@ -26,13 +26,13 @@ ro:
rows_label: Rânduri
unassigned_account: Trebuie să creezi un cont nou pentru rândurile neasignate?
show:
- account_mapping_description: Asignează toate conturile din fișierul tău importat conturilor existente din Maybe. Poți adăuga și conturi noi sau le poți lăsa necategorizate.
+ account_mapping_description: Asignează toate conturile din fișierul tău importat conturilor existente din %{product_name}. Poți adăuga și conturi noi sau le poți lăsa necategorizate.
account_mapping_title: Asignează-ți conturile
- account_type_mapping_description: Asignează toate tipurile de cont din fișierul tău importat celor din Maybe.
+ account_type_mapping_description: Asignează toate tipurile de cont din fișierul tău importat celor din %{product_name}.
account_type_mapping_title: Asignează-ți tipurile de cont
- category_mapping_description: Asignează toate categoriile din fișierul tău importat categoriilor existente din Maybe. Poți adăuga și categorii noi sau le poți lăsa necategorizate.
+ category_mapping_description: Asignează toate categoriile din fișierul tău importat categoriilor existente din %{product_name}. Poți adăuga și categorii noi sau le poți lăsa necategorizate.
category_mapping_title: Asignează-ți categoriile
- tag_mapping_description: Asignează toate etichetele din fișierul tău importat etichetelor existente din Maybe. Poți adăuga și etichete noi sau le poți lăsa necategorizate.
+ tag_mapping_description: Asignează toate etichetele din fișierul tău importat etichetelor existente din %{product_name}. Poți adăuga și etichete noi sau le poți lăsa necategorizate.
tag_mapping_title: Asignează-ți etichetele
uploads:
show:
diff --git a/config/locales/views/imports/tr.yml b/config/locales/views/imports/tr.yml
index 7aaaaf079..8296d655c 100644
--- a/config/locales/views/imports/tr.yml
+++ b/config/locales/views/imports/tr.yml
@@ -26,13 +26,13 @@ tr:
rows_label: Satırlar
unassigned_account: Atanmamış satırlar için yeni bir hesap oluşturmak ister misiniz?
show:
- account_mapping_description: "İçe aktardığınız dosyadaki tüm hesapları %{product}'deki mevcut hesaplara eşleyin. Ayrıca yeni hesaplar ekleyebilir veya kategorize etmeden bırakabilirsiniz."
+ account_mapping_description: "İçe aktardığınız dosyadaki tüm hesapları %{product_name}'deki mevcut hesaplara eşleyin. Ayrıca yeni hesaplar ekleyebilir veya kategorize etmeden bırakabilirsiniz."
account_mapping_title: Hesaplarınızı eşleyin
- account_type_mapping_description: "İçe aktardığınız dosyadaki tüm hesap türlerini %{product}'deki hesap türlerine eşleyin."
+ account_type_mapping_description: "İçe aktardığınız dosyadaki tüm hesap türlerini %{product_name}'deki hesap türlerine eşleyin."
account_type_mapping_title: Hesap türlerinizi eşleyin
- category_mapping_description: "İçe aktardığınız dosyadaki tüm kategorileri %{product}'deki mevcut kategorilere eşleyin. Ayrıca yeni kategoriler ekleyebilir veya kategorize etmeden bırakabilirsiniz."
+ category_mapping_description: "İçe aktardığınız dosyadaki tüm kategorileri %{product_name}'deki mevcut kategorilere eşleyin. Ayrıca yeni kategoriler ekleyebilir veya kategorize etmeden bırakabilirsiniz."
category_mapping_title: Kategorilerinizi eşleyin
- tag_mapping_description: "İçe aktardığınız dosyadaki tüm etiketleri %{product}'deki mevcut etiketlere eşleyin. Ayrıca yeni etiketler ekleyebilir veya kategorize etmeden bırakabilirsiniz."
+ tag_mapping_description: "İçe aktardığınız dosyadaki tüm etiketleri %{product_name}'deki mevcut etiketlere eşleyin. Ayrıca yeni etiketler ekleyebilir veya kategorize etmeden bırakabilirsiniz."
tag_mapping_title: Etiketlerinizi eşleyin
uploads:
show:
diff --git a/config/locales/views/imports/zh-CN.yml b/config/locales/views/imports/zh-CN.yml
index 3c5493f86..8ea66765b 100644
--- a/config/locales/views/imports/zh-CN.yml
+++ b/config/locales/views/imports/zh-CN.yml
@@ -34,13 +34,13 @@ zh-CN:
sure_mapping_label: "%{product_name} 中的 %{mapping}"
unassigned_account: 需要为未分配行创建新账户?
show:
- account_mapping_description: 将导入文件中的所有账户分配到 %{product} 的现有账户。您也可以新建账户或保留为未分类。
+ account_mapping_description: 将导入文件中的所有账户分配到 %{product_name} 的现有账户。您也可以新建账户或保留为未分类。
account_mapping_title: 分配账户
- account_type_mapping_description: 将导入文件中的所有账户类型分配到 %{product} 的账户类型
+ account_type_mapping_description: 将导入文件中的所有账户类型分配到 %{product_name} 的账户类型
account_type_mapping_title: 分配账户类型
- category_mapping_description: 将导入文件中的所有分类分配到 %{product} 的现有分类。您也可以新建分类或保留为未分类。
+ category_mapping_description: 将导入文件中的所有分类分配到 %{product_name} 的现有分类。您也可以新建分类或保留为未分类。
category_mapping_title: 分配分类
- tag_mapping_description: 将导入文件中的所有标签分配到 %{product} 的现有标签。您也可以新建标签或保留为未分类。
+ tag_mapping_description: 将导入文件中的所有标签分配到 %{product_name} 的现有标签。您也可以新建标签或保留为未分类。
tag_mapping_title: 分配标签
uploads:
show:
diff --git a/config/locales/views/imports/zh-TW.yml b/config/locales/views/imports/zh-TW.yml
index a7a47849b..6dbbba204 100644
--- a/config/locales/views/imports/zh-TW.yml
+++ b/config/locales/views/imports/zh-TW.yml
@@ -34,13 +34,13 @@ zh-TW:
rows_label: 資料列
unassigned_account: 需要為未分配的資料列建立新帳戶嗎?
show:
- account_mapping_description: 將匯入檔案中的帳戶對應到 Maybe 現有的帳戶。您也可以新增帳戶,或暫時不進行分類。
+ account_mapping_description: 將匯入檔案中的帳戶對應到 %{product_name} 現有的帳戶。您也可以新增帳戶,或暫時不進行分類。
account_mapping_title: 分配您的帳戶
- account_type_mapping_description: 將匯入檔案中的帳戶類型對應到 Maybe 的帳戶類型
+ account_type_mapping_description: 將匯入檔案中的帳戶類型對應到 %{product_name} 的帳戶類型
account_type_mapping_title: 分配您的帳戶類型
- category_mapping_description: 將匯入檔案中的類別對應到 Maybe 現有的類別。您也可以新增類別,或暫時不進行分類。
+ category_mapping_description: 將匯入檔案中的類別對應到 %{product_name} 現有的類別。您也可以新增類別,或暫時不進行分類。
category_mapping_title: 分配您的類別
- tag_mapping_description: 將匯入檔案中的標籤對應到 Maybe 現有的標籤。您也可以新增標籤,或暫時不進行分類。
+ tag_mapping_description: 將匯入檔案中的標籤對應到 %{product_name} 現有的標籤。您也可以新增標籤,或暫時不進行分類。
tag_mapping_title: 分配您的標籤
uploads:
show:
diff --git a/docs/hosting/ai.md b/docs/hosting/ai.md
index f13f79046..70c89d557 100644
--- a/docs/hosting/ai.md
+++ b/docs/hosting/ai.md
@@ -450,13 +450,18 @@ Pipelock scans for prompt injection, DLP violations, and tool poisoning. The ext
**`NO_PROXY` behavior (Helm/Kubernetes only):** The Helm chart's env template sets `NO_PROXY` to include `.svc.cluster.local` and other internal domains. This means in-cluster agent URLs (like `http://agent.namespace.svc.cluster.local:18789`) bypass the forward proxy and go directly. If your agent is in-cluster, its traffic won't be forward-proxy scanned (but MCP callbacks from the agent are still scanned by the reverse proxy). Docker Compose deployments use a different `NO_PROXY` set; check your compose file for the exact values.
-**`mcpToolPolicy` note:** The Helm chart's `pipelock.mcpToolPolicy.enabled` defaults to `true`. If you haven't defined any policy rules, disable it:
+**`mcpToolPolicy` note:** The Helm chart's `pipelock.mcpToolPolicy.enabled` defaults to `false`. Pipelock rejects an enabled tool policy with no rules, so the chart ships it off by default. To turn it on, define at least one rule and set `enabled: true`:
```yaml
# Helm values
pipelock:
mcpToolPolicy:
- enabled: false
+ enabled: true
+ action: warn
+ rules:
+ - name: example
+ toolPattern: "^shell$"
+ action: block
```
See the [Pipelock documentation](https://github.com/luckyPipewrench/pipelock) for tool policy configuration details.
diff --git a/docs/hosting/mcp.md b/docs/hosting/mcp.md
index 671feb700..db019163f 100644
--- a/docs/hosting/mcp.md
+++ b/docs/hosting/mcp.md
@@ -231,7 +231,7 @@ Pipelock provides:
- **Tool poisoning detection**: Prevents malicious tool call sequences
- **Policy enforcement**: Block or warn on suspicious patterns
-See the [Pipelock documentation](pipelock.md) and the example configuration in `compose.example.pipelock.yml` for setup instructions.
+See the [Pipelock documentation](pipelock.md) and the example configuration in `compose.example.ai.yml` for setup instructions.
### Network Security
diff --git a/docs/hosting/pipelock.md b/docs/hosting/pipelock.md
index 08c14fb13..0cd5ed126 100644
--- a/docs/hosting/pipelock.md
+++ b/docs/hosting/pipelock.md
@@ -77,13 +77,13 @@ Enable Pipelock in your Helm values:
pipelock:
enabled: true
image:
- tag: "2.2.0"
+ tag: "2.5.0"
mode: balanced
```
This creates a separate Deployment, Service, and ConfigMap. The chart auto-injects `HTTPS_PROXY`/`HTTP_PROXY`/`NO_PROXY` into web and worker pods.
-Recent pipelock releases add trusted domain allowlisting, MCP tool redirect profiles, enhanced tool poisoning detection (full JSON schema scanning), per-read kill switch preemption, signed action receipts, per-pattern DLP warn mode, and the `pipelock posture verify` / `pipelock session` CLI commands. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
+Recent pipelock releases add the Audit Packet v0 schema and language-portable verifiers (Go/TypeScript/Rust), request-body prompt-injection blocking, SPIFFE-strict inbound mediation envelopes, scanner attribution on MCP block receipts, trusted domain allowlisting, MCP tool redirect profiles, enhanced tool poisoning detection, per-read kill switch preemption, signed action receipts, per-pattern DLP warn mode, learn-and-lock behavioural contracts, the wedge-detection health watchdog, and the `pipelock posture verify` / `pipelock session` / `pipelock doctor` CLI commands. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
### Exposing MCP to external agents (Kubernetes)
@@ -149,6 +149,7 @@ The `pipelock.example.yaml` file (Docker Compose) or ConfigMap (Helm) controls s
| `trusted_domains` | Allow internal services whose public DNS resolves to private IPs |
| `forward_proxy` | Outbound HTTPS scanning (tunnel timeouts, idle timeouts) |
| `dlp` | Data loss prevention (scan env vars, built-in patterns) |
+| `request_body_scanning` | Scan outbound request bodies for prompt-injection and bodies/sensitive headers for DLP (pipelock 2.5+) |
| `response_scanning` | Scan LLM responses for prompt injection |
| `mcp_input_scanning` | Scan inbound MCP requests |
| `mcp_tool_scanning` | Validate tool calls, detect drift |
@@ -156,6 +157,7 @@ The `pipelock.example.yaml` file (Docker Compose) or ConfigMap (Helm) controls s
| `mcp_session_binding` | Pin tool inventory, detect manipulation |
| `tool_chain_detection` | Multi-step attack patterns |
| `websocket_proxy` | WebSocket frame scanning (disabled by default) |
+| `health_watchdog` | Wedge-detection on subsystem heartbeats, returns 503 on stall (pipelock 2.4+) |
| `logging` | Output format (json/text), verbosity |
For the Helm chart, most sections are configurable via `values.yaml`. For additional sections not covered by structured values (session profiling, data budgets, kill switch, sandbox, reverse proxy, adaptive enforcement), use the `extraConfig` escape hatch:
diff --git a/pipelock.example.yaml b/pipelock.example.yaml
index ee77d162f..4e2af49f9 100644
--- a/pipelock.example.yaml
+++ b/pipelock.example.yaml
@@ -1,12 +1,16 @@
# Pipelock configuration for Docker Compose
# See https://github.com/luckyPipewrench/pipelock for full options.
#
-# Recent additions: trusted_domains, redirect profiles, attack simulation,
-# security scoring, process sandbox, enhanced tool poisoning detection, signed
-# action receipts, per-pattern DLP warn mode, and the `pipelock posture verify`
-# / `pipelock session` CLIs.
+# Recent additions (2.5): Audit Packet v0 schema with Go/TypeScript/Rust
+# verifiers, request-body prompt-injection blocking, SPIFFE-strict inbound
+# mediation envelopes, scanner attribution on MCP block receipts, wedge-
+# detection health watchdog, learn-and-lock behavioural contracts, trusted
+# domains, redirect profiles, attack simulation, security scoring, process
+# sandbox, signed action receipts, per-pattern DLP warn mode, and the
+# `pipelock posture verify` / `pipelock session` / `pipelock doctor` CLIs.
# Run `pipelock simulate --config ">
<%= button_to authorize_enable_banking_item_path(@enable_banking_item),
method: :post,
params: { aspsp_name: aspsp[:name], new_connection: @new_connection },
diff --git a/app/views/import/confirms/show.html.erb b/app/views/import/confirms/show.html.erb
index 8560b761d..43afe9e70 100644
--- a/app/views/import/confirms/show.html.erb
+++ b/app/views/import/confirms/show.html.erb
@@ -67,7 +67,7 @@
<%= t(".#{step_mapping_class.name.demodulize.underscore}_title", import_type: @import.type.underscore.humanize) %>
- <%= t(".#{step_mapping_class.name.demodulize.underscore}_description", import_type: @import.type.underscore.humanize, product: product_name) %> + <%= t(".#{step_mapping_class.name.demodulize.underscore}_description", import_type: @import.type.underscore.humanize, product_name: product_name) %> |