Skip to content
Olyx

Policies and restricted content

Configure immutable policies, blocking rules, redaction replacements, and safe YAML.

Use policies to choose what Guardrails reports, blocks, and redacts.

An Olyx::Guardrails::Policy cannot be changed after it is created. Guardrails checks its settings and compiles its regular expressions when you create it, so invalid settings fail before the policy is used.

require "olyx/guardrails"
policy = Olyx::Guardrails::Policy.new(
name: "production",
max_input_length: 4_000,
block_pii: true,
block_injections: true,
block_secrets: true,
llm_failure_mode: :block,
secret_patterns: ["company-token-[a-z0-9]{24}"],
rules: [
{
name: :confidential_projects,
description: "Internal project identifiers",
terms: ["Project Falcon"],
patterns: [/\bPF-\d{4}\b/],
match: :whole_word,
block: true,
replacement: "[CONFIDENTIAL_PROJECT]"
}
]
)
Option Default Contract
name "default" Non-blank String, at most 100 characters
max_input_length 10_000 Non-negative Integer measured in Ruby characters
block_pii false Blocks when a PII finding exists
block_injections true Blocks when an injection finding exists
block_secrets false Blocks when a secret finding exists
llm_failure_mode :allow One of :allow, :block, or :raise
secret_patterns [] Array of regular-expression source Strings
rules [] Array of PolicyRule objects or String/Symbol-keyed Hashes

All Boolean options require literal true or false. Policy objects and their compiled rule collections are frozen.

Policy.default returns one reused immutable policy. Its behavior is:

Finding Reported Blocked
Input longer than 10,000 characters Yes Yes
Prompt injection Yes Yes
PII Yes No
Secret Yes No
Restricted content Not configured No
Supplied LLM provider fails Yes, under llm_analysis No

An explicit policy is recommended for production. In particular, applications that require semantic analysis should set llm_failure_mode to :block or :raise.

secret_patterns extends credential-format detection. Matches remain in the secret category and use the standard secret replacement.

policy = Olyx::Guardrails::Policy.new(
secret_patterns: [
"company-token-[a-z0-9]{24}",
"internal-key-[A-F0-9]{32}"
]
)

Use a policy rule when a finding needs an organization-specific identifier, description, blocking decision, or replacement.

rule = Olyx::Guardrails::PolicyRule.new(
name: :export_controlled_terms,
terms: ["Program Orion"],
match: :whole_word,
block: true,
description: "Export-controlled program names",
replacement: "[EXPORT_CONTROLLED]"
)
Option Default Contract
name required String or Symbol matching [A-Za-z][A-Za-z0-9_.:-]*
terms [] Array of non-empty Strings
patterns [] Array of Strings or Regexps
match :substring :substring, :whole_word, or :regexp; applies to terms
block true Literal Boolean
description nil Non-blank String up to 500 characters, or nil
replacement generated Single-line String from 1 through 100 characters

Every rule defines at least one term or pattern. Rule names are unique within a policy.

When replacement is omitted, the default is derived from the rule name:

Olyx::Guardrails::PolicyRule.new(
name: :confidential_project,
terms: ["Project Falcon"]
).replacement
# => "[RESTRICTED:CONFIDENTIAL_PROJECT]"

:substring is the default. Terms are escaped and matched case-insensitively anywhere in the input.

{ name: :project, terms: ["Falcon"], match: :substring }

This rule matches both Falcon and Falconry.

:whole_word adds alphanumeric and underscore boundaries around the escaped term.

{ name: :project, terms: ["Falcon"], match: :whole_word }

This rule matches Project Falcon but not Falconry.

:regexp interprets values under terms as regular-expression source.

{ name: :project_code, terms: ["PF-\\d{4}"], match: :regexp }

Use patterns when regular-expression semantics should be explicit:

{
name: :project_code,
patterns: ["\\bPF-[0-9]{4}\\b", /ORION-\d+/i]
}

String patterns compile case-insensitively. Regexps retain their flags. All compiled expressions use a 100-millisecond match timeout and must not match an empty string.

Configured regular expressions are trusted application configuration. Review them for excessive backtracking before deployment.

A blocking rule causes Guardrails.check to return allowed: false. A monitoring-only rule records the finding without rejecting the input.

rules = [
{
name: :confidential_projects,
terms: ["Project Falcon"],
block: true
},
{
name: :competitor_references,
terms: ["Competitor Corp"],
block: false
}
]

Both rules participate in Guardrails.redact. The block option controls the decision, not whether a transformation is available.

Policy findings never contain the matched restricted text:

{
rule: "confidential_projects",
description: "Internal project identifiers",
blocked: true,
matched: "[REDACTED]",
fingerprint: "sha256:...",
start: 8,
end: 22
}

description is omitted when the rule has no description. start is inclusive, and end is exclusive. Fingerprints support correlation without revealing plaintext.

Policy.from_h accepts top-level String or Symbol keys:

policy = Olyx::Guardrails::Policy.from_h(
"name" => "production",
"block_secrets" => true,
"rules" => [
{
"name" => "confidential_projects",
"terms" => ["Project Falcon"]
}
]
)

Rule hashes may also use String or Symbol keys. Unknown keys and invalid values raise ArgumentError; configuration does not silently fall back to defaults.

The Rails generator creates config/olyx_guardrails.yml with one policy per environment:

production:
name: production
max_input_length: 4000
block_pii: true
block_injections: true
block_secrets: true
llm_failure_mode: block
secret_patterns:
- 'company-token-[a-z0-9]{24}'
rules:
- name: confidential_projects
description: Internal project names
terms:
- 'Project Falcon'
match: whole_word
block: true
replacement: '[CONFIDENTIAL_PROJECT]'

The loader uses YAML.safe_load_file with aliases and custom classes disabled. ERB is not evaluated. Missing, unreadable, malformed, unsafe, or invalid policy files raise Olyx::Guardrails::ConfigurationError during Rails boot.

A file may instead contain one direct policy hash. Do not mix direct policy keys with environment sections.

Construct a policy once and reuse it for decisions, redaction, and notifications:

decision = Olyx::Guardrails.check(input, policy: policy)
redaction = Olyx::Guardrails.redact(input, policy: policy)
notifier = Olyx::Guardrails::Notifier.new(
policy: policy,
handlers: { audit: ->(event) { AuditLog.write(event) } }
)

Passing the same policy to the notifier ensures that previews, metadata, and handler errors use the same restricted-content replacements.

See the API reference for the exact constructor, readers, and exception contracts.