aisafe 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. aisafe/__init__.py +141 -0
  2. aisafe/cli.py +197 -0
  3. aisafe/config/__init__.py +54 -0
  4. aisafe/config/attest-levels.yaml +58 -0
  5. aisafe/config/default.yaml +163 -0
  6. aisafe/config/eu_high_risk.yaml +180 -0
  7. aisafe/config/nemo_rails/config.yml +57 -0
  8. aisafe/config/nemo_rails/rails.co +140 -0
  9. aisafe/config/prices.yaml +72 -0
  10. aisafe/config/settings.py +372 -0
  11. aisafe/core/__init__.py +34 -0
  12. aisafe/core/base.py +283 -0
  13. aisafe/core/exceptions.py +38 -0
  14. aisafe/core/measurement.py +435 -0
  15. aisafe/core/pipeline.py +470 -0
  16. aisafe/core/registry.py +24 -0
  17. aisafe/devtools/__init__.py +0 -0
  18. aisafe/devtools/_config.py +114 -0
  19. aisafe/devtools/_git.py +148 -0
  20. aisafe/devtools/attest.py +1409 -0
  21. aisafe/devtools/audit/__init__.py +26 -0
  22. aisafe/devtools/audit/adapters.py +1796 -0
  23. aisafe/devtools/audit/baseline.py +589 -0
  24. aisafe/devtools/audit/configs.py +1080 -0
  25. aisafe/devtools/audit/discover.py +2053 -0
  26. aisafe/devtools/audit/html.py +1497 -0
  27. aisafe/devtools/audit/lint_bridge.py +137 -0
  28. aisafe/devtools/audit/main.py +986 -0
  29. aisafe/devtools/audit/model.py +951 -0
  30. aisafe/devtools/audit/patterns.py +1557 -0
  31. aisafe/devtools/audit/persons_patterns.py +380 -0
  32. aisafe/devtools/audit/pydeep.py +1942 -0
  33. aisafe/devtools/audit/report.py +1218 -0
  34. aisafe/devtools/audit/rules/__init__.py +551 -0
  35. aisafe/devtools/audit/rules/blast_radius.py +1140 -0
  36. aisafe/devtools/audit/rules/evals.py +720 -0
  37. aisafe/devtools/audit/rules/governance.py +398 -0
  38. aisafe/devtools/audit/rules/guards.py +1270 -0
  39. aisafe/devtools/audit/rules/irreversible.py +394 -0
  40. aisafe/devtools/audit/rules/observability.py +402 -0
  41. aisafe/devtools/audit/rules/persons.py +1125 -0
  42. aisafe/devtools/audit/rules/secrets_pii.py +675 -0
  43. aisafe/devtools/audit/rules/sinks.py +467 -0
  44. aisafe/devtools/audit/rules/supply_chain.py +703 -0
  45. aisafe/devtools/audit/rules/trust_boundary.py +761 -0
  46. aisafe/devtools/audit/semgrep/aisafe-sinks.yaml +435 -0
  47. aisafe/devtools/audit/vocab.py +475 -0
  48. aisafe/devtools/audit/walk.py +794 -0
  49. aisafe/devtools/decide.py +1056 -0
  50. aisafe/devtools/euaiact_lint.py +337 -0
  51. aisafe/devtools/fleet.py +1025 -0
  52. aisafe/devtools/hook.py +1712 -0
  53. aisafe/devtools/hosts.py +230 -0
  54. aisafe/devtools/measure.py +1058 -0
  55. aisafe/devtools/misalignment/__init__.py +0 -0
  56. aisafe/devtools/misalignment/rules/__init__.py +527 -0
  57. aisafe/devtools/misalignment_check.py +299 -0
  58. aisafe/devtools/prices.py +277 -0
  59. aisafe/devtools/probe.py +918 -0
  60. aisafe/devtools/skill.py +357 -0
  61. aisafe/devtools/system_card.py +375 -0
  62. aisafe/integrations/__init__.py +10 -0
  63. aisafe/integrations/anthropic_middleware.py +115 -0
  64. aisafe/integrations/fastapi_middleware.py +233 -0
  65. aisafe/integrations/langchain_callback.py +135 -0
  66. aisafe/integrations/nemo_rails.py +433 -0
  67. aisafe/modules/__init__.py +1 -0
  68. aisafe/modules/input/__init__.py +6 -0
  69. aisafe/modules/input/advanced_injection_detectors.py +643 -0
  70. aisafe/modules/input/llm_input_filter.py +194 -0
  71. aisafe/modules/input/pii_detector.py +348 -0
  72. aisafe/modules/input/prompt_injection.py +422 -0
  73. aisafe/modules/input/rate_limiter.py +172 -0
  74. aisafe/modules/llm_judges/__init__.py +80 -0
  75. aisafe/modules/llm_judges/base.py +289 -0
  76. aisafe/modules/llm_judges/cache.py +198 -0
  77. aisafe/modules/llm_judges/claude_judge.py +261 -0
  78. aisafe/modules/llm_judges/estimate.py +204 -0
  79. aisafe/modules/llm_judges/llamaguard.py +379 -0
  80. aisafe/modules/llm_judges/openai_mod.py +151 -0
  81. aisafe/modules/observability/__init__.py +4 -0
  82. aisafe/modules/observability/audit_logger.py +266 -0
  83. aisafe/modules/observability/otel.py +402 -0
  84. aisafe/modules/output/__init__.py +13 -0
  85. aisafe/modules/output/ai_disclosure.py +197 -0
  86. aisafe/modules/output/llm_output_filter.py +193 -0
  87. aisafe/modules/output/manipulation.py +371 -0
  88. aisafe/modules/output/toxicity.py +208 -0
  89. aisafe/modules/policy/__init__.py +4 -0
  90. aisafe/modules/policy/code_analyzer/__init__.py +21 -0
  91. aisafe/modules/policy/code_analyzer/analyzer.py +430 -0
  92. aisafe/modules/policy/code_analyzer/reporters.py +606 -0
  93. aisafe/modules/policy/code_analyzer/rules/__init__.py +877 -0
  94. aisafe/modules/policy/eu_ai_act.py +478 -0
  95. aisafe/modules/policy/nist_ai_rmf.py +511 -0
  96. aisafe/modules/processing/__init__.py +4 -0
  97. aisafe/modules/processing/llm_tool_filter.py +412 -0
  98. aisafe/modules/processing/tool_policy.py +445 -0
  99. aisafe/probes/__init__.py +13 -0
  100. aisafe/probes/benign_traffic.yaml +252 -0
  101. aisafe/probes/encoding_bypass.yaml +89 -0
  102. aisafe/probes/manipulation_elicitation.yaml +82 -0
  103. aisafe/probes/manipulation_responses.yaml +121 -0
  104. aisafe/probes/pii_echo.yaml +86 -0
  105. aisafe/probes/prompt_injection.yaml +90 -0
  106. aisafe/probes/system_prompt_extraction.yaml +91 -0
  107. aisafe/probes/tool_abuse.yaml +71 -0
  108. aisafe/probes/toxicity_elicitation.yaml +87 -0
  109. aisafe/skills/__init__.py +86 -0
  110. aisafe/skills/ai-safety-audit/SKILL.md +371 -0
  111. aisafe/skills/ai-safety-audit/agents/openai.yaml +6 -0
  112. aisafe/skills/ai-safety-audit/references/apply/generic.md +112 -0
  113. aisafe/skills/ai-safety-audit/references/apply/go.md +106 -0
  114. aisafe/skills/ai-safety-audit/references/apply/python.md +547 -0
  115. aisafe/skills/ai-safety-audit/references/apply/typescript.md +114 -0
  116. aisafe/skills/ai-safety-audit/references/controls.md +720 -0
  117. aisafe/skills/ai-safety-audit/references/hosts.md +113 -0
  118. aisafe/skills/ai-safety-audit/references/levels.md +80 -0
  119. aisafe/skills/ai-safety-audit/references/report-format.md +389 -0
  120. aisafe/skills/ai-safety-audit/scripts/attest.ps1 +27 -0
  121. aisafe/skills/ai-safety-audit/scripts/attest.sh +27 -0
  122. aisafe/skills/ai-safety-audit/scripts/audit.ps1 +27 -0
  123. aisafe/skills/ai-safety-audit/scripts/audit.sh +27 -0
  124. aisafe/skills/ai-safety-audit/scripts/hook.ps1 +25 -0
  125. aisafe/skills/ai-safety-audit/scripts/hook.sh +24 -0
  126. aisafe/skills/ai-safety-audit/scripts/verify.ps1 +140 -0
  127. aisafe/skills/ai-safety-audit/scripts/verify.sh +131 -0
  128. aisafe-0.1.0.dist-info/METADATA +1493 -0
  129. aisafe-0.1.0.dist-info/RECORD +133 -0
  130. aisafe-0.1.0.dist-info/WHEEL +5 -0
  131. aisafe-0.1.0.dist-info/entry_points.txt +4 -0
  132. aisafe-0.1.0.dist-info/licenses/LICENSE +21 -0
  133. aisafe-0.1.0.dist-info/top_level.txt +1 -0
aisafe/__init__.py ADDED
@@ -0,0 +1,141 @@
1
+ """
2
+ __init__.py
3
+ -----------
4
+ AnyAISafe — public API surface.
5
+
6
+ Runtime guardrails (use in your application):
7
+ from aisafe import GuardrailPipeline
8
+ from aisafe import PIIDetector, PromptInjectionGuard
9
+ from aisafe import ToxicityFilter
10
+ from aisafe import ToolPolicyGuard, ToolPolicy
11
+ from aisafe import EUAIActCompliance, RiskTier
12
+ from aisafe import AuditLogger
13
+
14
+ Static code analyzer (use in CI / pre-commit):
15
+ from aisafe import EUAIActCodeAnalyzer, ScanReport
16
+ from aisafe import TerminalReporter, JSONReporter, SARIFReporter
17
+ # or via CLI: aisafe lint src/
18
+ """
19
+
20
+ import importlib
21
+
22
+ from aisafe.core.base import (
23
+ Action,
24
+ CheckResult,
25
+ Finding,
26
+ GuardrailBase,
27
+ GuardrailStage,
28
+ PipelineResult,
29
+ Severity,
30
+ )
31
+ from aisafe.core.exceptions import (
32
+ GuardrailBlockedError,
33
+ GuardrailConfigError,
34
+ PolicyViolationError,
35
+ )
36
+ from aisafe.core.pipeline import GuardrailPipeline
37
+
38
+ # Input modules
39
+ from aisafe.modules.input.pii_detector import PIIDetector, PIIRestorer
40
+ from aisafe.modules.input.prompt_injection import PromptInjectionGuard
41
+ from aisafe.modules.input.rate_limiter import RateLimiter
42
+
43
+ # LLM judges (the base class; concrete judges need their provider SDK)
44
+ from aisafe.modules.llm_judges.base import LLMJudgeBase
45
+
46
+ # Output modules
47
+ from aisafe.modules.output.ai_disclosure import AIDisclosureGuard
48
+ from aisafe.modules.output.llm_output_filter import LLMOutputFilter
49
+ from aisafe.modules.output.manipulation import ManipulationGuard
50
+ from aisafe.modules.output.toxicity import ToxicityFilter
51
+
52
+ # Policy — static code analyzer
53
+ from aisafe.modules.policy.code_analyzer.analyzer import EUAIActCodeAnalyzer, ScanReport
54
+ from aisafe.modules.policy.code_analyzer.reporters import (
55
+ JSONReporter,
56
+ MarkdownReporter,
57
+ SARIFReporter,
58
+ TerminalReporter,
59
+ )
60
+
61
+ # Policy — runtime guardrails
62
+ from aisafe.modules.policy.eu_ai_act import EUAIActCompliance, RiskTier
63
+ from aisafe.modules.policy.nist_ai_rmf import ImpactLevel, NISTAIRMFCompliance
64
+
65
+ # Processing modules
66
+ from aisafe.modules.processing.llm_tool_filter import LLMToolFilter
67
+ from aisafe.modules.processing.tool_policy import ToolPolicy, ToolPolicyGuard
68
+
69
+ # Observability is imported on first use (PEP 562). `otel.py` pulls in the
70
+ # OpenTelemetry SDK, about a quarter of a second that every `aisafe` CLI run and every
71
+ # agent hook would otherwise pay before doing anything; `otel.py` still guards the
72
+ # optional dependency itself. Guards stay eager: `@register_guard` fills the registry
73
+ # `GuardrailPipeline.from_config` reads, and a lazy guard would be an unregistered name.
74
+ _LAZY_ATTRIBUTES = {
75
+ "AuditLogger": ("aisafe.modules.observability.audit_logger", "AuditLogger"),
76
+ "TelemetryProvider": ("aisafe.modules.observability.otel", "TelemetryProvider"),
77
+ }
78
+
79
+
80
+ def __getattr__(name: str):
81
+ target = _LAZY_ATTRIBUTES.get(name)
82
+ if target is None:
83
+ raise AttributeError(f"module 'aisafe' has no attribute {name!r}")
84
+ module = importlib.import_module(target[0])
85
+ value = getattr(module, target[1])
86
+ globals()[name] = value
87
+ return value
88
+
89
+
90
+ def __dir__() -> list[str]:
91
+ return sorted(set(globals()) | set(__all__))
92
+
93
+
94
+ __version__ = "0.1.0"
95
+ __all__ = [
96
+ # Pipeline
97
+ "GuardrailPipeline",
98
+ # Base types
99
+ "GuardrailBase",
100
+ "CheckResult",
101
+ "PipelineResult",
102
+ "Finding",
103
+ "Severity",
104
+ "Action",
105
+ "GuardrailStage",
106
+ # Exceptions
107
+ "GuardrailBlockedError",
108
+ "GuardrailConfigError",
109
+ "PolicyViolationError",
110
+ # Input
111
+ "PIIDetector",
112
+ "PIIRestorer",
113
+ "PromptInjectionGuard",
114
+ "RateLimiter",
115
+ # Processing
116
+ "ToolPolicyGuard",
117
+ "ToolPolicy",
118
+ "LLMToolFilter",
119
+ # Output
120
+ "ToxicityFilter",
121
+ "LLMOutputFilter",
122
+ "ManipulationGuard",
123
+ "AIDisclosureGuard",
124
+ # LLM judges
125
+ "LLMJudgeBase",
126
+ # Policy — runtime
127
+ "EUAIActCompliance",
128
+ "RiskTier",
129
+ "NISTAIRMFCompliance",
130
+ "ImpactLevel",
131
+ # Policy — static analyzer
132
+ "EUAIActCodeAnalyzer",
133
+ "ScanReport",
134
+ "TerminalReporter",
135
+ "JSONReporter",
136
+ "SARIFReporter",
137
+ "MarkdownReporter",
138
+ # Observability
139
+ "AuditLogger",
140
+ "TelemetryProvider",
141
+ ]
aisafe/cli.py ADDED
@@ -0,0 +1,197 @@
1
+ """
2
+ src/aisafe/cli.py
3
+ ---------------
4
+ Single entry point for the AnyAISafe developer tools.
5
+
6
+ aisafe --version
7
+ aisafe lint src/
8
+ aisafe lint src/ --format sarif --output results.sarif
9
+ aisafe misalign src/ --fail-on-warnings
10
+ aisafe audit . --format json -o audit-report.json
11
+ aisafe skill install --host all
12
+
13
+ Every subcommand is a thin wrapper around a tool in `aisafe.devtools`: `lint`,
14
+ `misalign`, `init`, `probe`, `measure`, `audit`, `skill`, `decide`, `hook`, `attest` and
15
+ `fleet`. Each is imported
16
+ only when invoked, so `aisafe lint` never pays for the audit engine. Everything
17
+ after the subcommand is handed to the underlying tool untouched, so their
18
+ flags, defaults and exit codes are unchanged:
19
+
20
+ 0 no errors (warnings/info allowed)
21
+ 1 errors found
22
+ 2 fatal error (bad args, parse failure)
23
+
24
+ `audit` adds 130 for an interrupted run; `skill` returns 1 when an install is
25
+ refused or an installed copy differs from the packaged skill.
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ import argparse
31
+ import sys
32
+ from typing import Callable, Sequence
33
+
34
+ from aisafe import __version__
35
+
36
+ __all__ = ["main", "build_parser"]
37
+
38
+ _EPILOG = """
39
+ Commands:
40
+ lint EU AI Act static compliance analysis (was: euaiact-lint)
41
+ misalign AI misalignment static analysis (was: misalignment-check)
42
+ init Write an ai-system-card.yaml for the system under assessment
43
+ probe Send a fixed attack corpus to a live endpoint and report what got through
44
+ measure Report what each guard catches, what it breaks, and what it costs
45
+ audit Static AI-safety audit of a repository: findings describe evidence, never verdicts
46
+ skill Install the packaged ai-safety-audit agent skill into host skill directories
47
+ decide What each proposed control costs (latency, tokens, usd, human load) against the declared budgets
48
+ hook Agent-host hooks: gate protected paths, secret literals and unsafe shell; re-audit edits; Stop gate
49
+ attest Evaluate the level criteria against the written documents; a named owner signs the result
50
+ fleet Audit every repository in a list, one subprocess each, and aggregate the counts
51
+
52
+ Run `aisafe <command> --help` for a command's own options.
53
+
54
+ Examples:
55
+ aisafe lint src/
56
+ aisafe lint src/ --format sarif --output results.sarif
57
+ aisafe lint src/ --errors-only
58
+ aisafe lint --staged # pre-commit
59
+ aisafe misalign src/ --fail-on-warnings
60
+ aisafe init --defaults
61
+ aisafe probe http://localhost:8000/chat --response-path '$.response'
62
+ aisafe measure
63
+ aisafe audit . --format json -o audit-report.json
64
+ aisafe audit . --baseline audit-baseline.json --fail-on high
65
+ aisafe skill install --host all
66
+ aisafe skill diff --host all
67
+ aisafe decide --requests-per-day 20000 --p99-budget-ms 250 --monthly-budget-usd 300
68
+ aisafe hook install --host claude --yes
69
+ aisafe hook list
70
+ aisafe attest . --owner "J. Doe <risk owner>" --html
71
+ aisafe attest . --check --require-level 2 # CI
72
+ aisafe fleet fleet.yaml --jobs 4 --proposal
73
+ """
74
+
75
+
76
+ def _lint(argv: Sequence[str]) -> int:
77
+ from aisafe.devtools.euaiact_lint import main as lint_main
78
+
79
+ return lint_main(list(argv))
80
+
81
+
82
+ def _misalign(argv: Sequence[str]) -> int:
83
+ from aisafe.devtools.misalignment_check import main as misalign_main
84
+
85
+ return misalign_main(list(argv))
86
+
87
+
88
+ def _init(argv: Sequence[str]) -> int:
89
+ from aisafe.devtools.system_card import main as init_main
90
+
91
+ return init_main(list(argv))
92
+
93
+
94
+ def _probe(argv: Sequence[str]) -> int:
95
+ from aisafe.devtools.probe import main as probe_main
96
+
97
+ return probe_main(list(argv))
98
+
99
+
100
+ def _measure(argv: Sequence[str]) -> int:
101
+ from aisafe.devtools.measure import main as measure_main
102
+
103
+ return measure_main(list(argv))
104
+
105
+
106
+ def _audit(argv: Sequence[str]) -> int:
107
+ from aisafe.devtools.audit.main import main as audit_main
108
+
109
+ return audit_main(list(argv))
110
+
111
+
112
+ def _skill(argv: Sequence[str]) -> int:
113
+ from aisafe.devtools.skill import main as skill_main
114
+
115
+ return skill_main(list(argv))
116
+
117
+
118
+ def _decide(argv: Sequence[str]) -> int:
119
+ from aisafe.devtools.decide import main as decide_main
120
+
121
+ return decide_main(list(argv))
122
+
123
+
124
+ def _hook(argv: Sequence[str]) -> int:
125
+ from aisafe.devtools.hook import main as hook_main
126
+
127
+ return hook_main(list(argv))
128
+
129
+
130
+ def _attest(argv: Sequence[str]) -> int:
131
+ from aisafe.devtools.attest import main as attest_main
132
+
133
+ return attest_main(list(argv))
134
+
135
+
136
+ def _fleet(argv: Sequence[str]) -> int:
137
+ from aisafe.devtools.fleet import main as fleet_main
138
+
139
+ return fleet_main(list(argv))
140
+
141
+
142
+ COMMANDS: dict[str, Callable[[Sequence[str]], int]] = {
143
+ "lint": _lint,
144
+ "misalign": _misalign,
145
+ "init": _init,
146
+ "probe": _probe,
147
+ "measure": _measure,
148
+ "audit": _audit,
149
+ "skill": _skill,
150
+ "decide": _decide,
151
+ "hook": _hook,
152
+ "attest": _attest,
153
+ "fleet": _fleet,
154
+ }
155
+
156
+
157
+ def build_parser() -> argparse.ArgumentParser:
158
+ p = argparse.ArgumentParser(
159
+ prog="aisafe",
160
+ description="AnyAISafe developer tools.",
161
+ formatter_class=argparse.RawDescriptionHelpFormatter,
162
+ epilog=_EPILOG,
163
+ )
164
+ p.add_argument(
165
+ "--version",
166
+ "-V",
167
+ action="version",
168
+ version=f"aisafe {__version__}",
169
+ )
170
+ p.add_argument(
171
+ "command",
172
+ choices=sorted(COMMANDS),
173
+ help="Subcommand to run",
174
+ )
175
+ # REMAINDER hands the rest through verbatim, so each tool keeps its own
176
+ # flags, help text and pyproject-sourced defaults.
177
+ p.add_argument(
178
+ "args",
179
+ nargs=argparse.REMAINDER,
180
+ help="Arguments passed through to the subcommand",
181
+ )
182
+ return p
183
+
184
+
185
+ def main(argv: list[str] | None = None) -> int:
186
+ parser = build_parser()
187
+ if argv is None:
188
+ argv = sys.argv[1:]
189
+ if not argv:
190
+ parser.print_help()
191
+ return 2
192
+ ns = parser.parse_args(argv)
193
+ return COMMANDS[ns.command](ns.args)
194
+
195
+
196
+ if __name__ == "__main__":
197
+ sys.exit(main())
@@ -0,0 +1,54 @@
1
+ """
2
+ src/aisafe/config/__init__.py
3
+ ---------------------------
4
+ Packaged configuration presets.
5
+
6
+ The YAML presets ship as package data, so they are readable from an installed
7
+ wheel via importlib.resources -- not just from a source checkout. A copy is
8
+ also kept at the repo-root `config/` directory for local development; the two
9
+ are identical.
10
+
11
+ from aisafe.config import preset_path, load_preset
12
+
13
+ GuardrailPipeline.from_config(preset_path("default.yaml"))
14
+ text = load_preset("eu_high_risk.yaml")
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from contextlib import ExitStack
20
+ from importlib import resources
21
+ from pathlib import Path
22
+
23
+ __all__ = ["PRESETS", "PRICES_FILE", "ATTEST_LEVELS_FILE", "preset_path", "load_preset"]
24
+
25
+ # Pipeline presets: each builds a GuardrailPipeline.
26
+ PRESETS = ("default.yaml", "eu_high_risk.yaml")
27
+ # Other packaged data read through `preset_path()`; not pipelines, so not in PRESETS.
28
+ PRICES_FILE = "prices.yaml" # the dated price table `aisafe decide` joins tokens with
29
+ ATTEST_LEVELS_FILE = "attest-levels.yaml" # the level criteria `aisafe attest` checks
30
+
31
+ # Keeps extracted resources alive for the process lifetime. Needed when the
32
+ # package is loaded from a zip, where as_file() materialises a temp copy.
33
+ _FILES = ExitStack()
34
+
35
+
36
+ def preset_path(name: str) -> Path:
37
+ """
38
+ Filesystem path to a packaged preset (e.g. "default.yaml", or
39
+ "nemo_rails/config.yml"). Works from a wheel as well as a checkout.
40
+ """
41
+ resource = resources.files(__package__)
42
+ for part in name.split("/"):
43
+ resource = resource / part
44
+ if not resource.is_file():
45
+ raise FileNotFoundError(f"No packaged config named {name!r}")
46
+ return _FILES.enter_context(resources.as_file(resource))
47
+
48
+
49
+ def load_preset(name: str) -> str:
50
+ """Read a packaged preset as text."""
51
+ resource = resources.files(__package__)
52
+ for part in name.split("/"):
53
+ resource = resource / part
54
+ return resource.read_text(encoding="utf-8")
@@ -0,0 +1,58 @@
1
+ # attest-levels.yaml
2
+ # ---------------------------------------------------------------------------
3
+ # The criteria `aisafe attest` evaluates. A level is reached when every criterion of
4
+ # that level and of every level below it is met. The level is a list of criteria met
5
+ # on a date, signed by a named owner; it is not a compliance verdict, and no renderer
6
+ # calls it one.
7
+ #
8
+ # Shipped in the wheel (src/aisafe/config/) and mirrored at config/; the two are kept
9
+ # identical by a test. `--level-criteria PATH` points `aisafe attest` at another file.
10
+ #
11
+ # Criterion kinds (attest.CRITERION_KINDS):
12
+ # report_present(max_age_days) an audit report, fresh enough
13
+ # report_names_head report.target.git_sha equals HEAD
14
+ # unknown_listed the report carries its UNKNOWN list
15
+ # no_open_findings_at_or_above(severity) every finding at or above it has an accepted reason
16
+ # external_tools_attempted no external scanner skipped by --no-external
17
+ # accepted_reasons_present every baseline fingerprint carries a reason
18
+ # document_present(document, max_age_days) a measure | probe | decision document, fresh
19
+ # measure_thresholds no guard over a declared threshold, none unavailable
20
+ # probe_passing_if_present failed == 0 and errors == 0 when a probe report exists
21
+ # rules_closed(rules) no open finding of those rules
22
+ # card_fields_set(fields) the system card's listed fields are not placeholders
23
+ # card_section_fresh(section, fields, date_field, max_age_days) a card block set, recently dated
24
+ # accepted_risks_owned every accepted risk is written next to the owner
25
+ # tree_clean no uncommitted changes (governed = reproducible)
26
+ # ---------------------------------------------------------------------------
27
+ schema: aisg/1
28
+ kind: attest-levels
29
+ review_interval_days: 90
30
+ levels:
31
+ - level: 0
32
+ name: audited
33
+ criteria:
34
+ - {id: L0.report, kind: report_present, max_age_days: 30}
35
+ - {id: L0.commit, kind: report_names_head}
36
+ - {id: L0.unknown, kind: unknown_listed}
37
+ - level: 1
38
+ name: triaged
39
+ criteria:
40
+ - {id: L1.no_open_high, kind: no_open_findings_at_or_above, severity: high}
41
+ - {id: L1.scanners, kind: external_tools_attempted}
42
+ - {id: L1.reasons, kind: accepted_reasons_present}
43
+ - level: 2
44
+ name: measured
45
+ criteria:
46
+ - {id: L2.measure, kind: document_present, document: measure, max_age_days: 30}
47
+ - {id: L2.thresholds, kind: measure_thresholds}
48
+ - {id: L2.probe, kind: probe_passing_if_present}
49
+ - {id: L2.decision, kind: document_present, document: decision, max_age_days: 30}
50
+ - {id: L2.evals_ci, kind: rules_closed, rules: [AUD-901, AUD-903]}
51
+ - level: 3
52
+ name: governed
53
+ criteria:
54
+ - {id: L3.card, kind: card_fields_set, fields: [system.purpose, affected_persons, incident_contact, risk_tier, deployment]}
55
+ - {id: L3.prompt_audit, kind: card_section_fresh, section: prompt_audit, fields: [reviewed_at, reviewer], date_field: reviewed_at, max_age_days: 180}
56
+ - {id: L3.controls, kind: rules_closed, rules: [AUD-107, AUD-701, AUD-702, AUD-703, AUD-1107]}
57
+ - {id: L3.owner, kind: accepted_risks_owned}
58
+ - {id: L3.tree, kind: tree_clean}
@@ -0,0 +1,163 @@
1
+ # config/default.yaml
2
+ # -------------------------------------------------------
3
+ # AnyAISafe — Default Pipeline Configuration
4
+ # -------------------------------------------------------
5
+ # All modules are optional. Set enabled: false to skip any.
6
+ # Override per environment: production.yaml, eu_high_risk.yaml, etc.
7
+
8
+ pipeline:
9
+ mode: async
10
+ parallel_checks: true # Run input checks in parallel for lower latency
11
+ fail_open: false # If true, guardrail errors allow traffic through (NOT recommended for prod)
12
+ request_timeout: 30.0 # Max seconds for the LLM call in run_full() (0 = no timeout)
13
+
14
+ # ⑤ OBSERVABILITY (OpenTelemetry)
15
+ # Install: pip install "aisafe[otel]"
16
+ # Pass a TelemetryProvider instance to GuardrailPipeline(telemetry_provider=...).
17
+ # Backends: set exporter to "otlp" and point otlp_endpoint at any OTLP collector
18
+ # (Jaeger, Zipkin, Datadog, Honeycomb, Grafana Tempo, AWS X-Ray via ADOT, etc.)
19
+ #
20
+ # observability:
21
+ # enabled: true
22
+ # service_name: my-ai-system
23
+ # exporter: console # "console" | "otlp" | "none"
24
+ # otlp_endpoint: http://localhost:4317
25
+ # otlp_protocol: grpc # "grpc" | "http"
26
+ # metric_export_interval_ms: 60000
27
+
28
+ # ① INPUT GUARDRAILS
29
+ input:
30
+ pii_detector:
31
+ enabled: true
32
+ action: redact # redact | block | flag
33
+ entities:
34
+ - EMAIL
35
+ - PHONE_US
36
+ - PHONE_INTL
37
+ - SSN
38
+ - CREDIT_CARD
39
+ - IP_ADDRESS
40
+ use_presidio: false # Set true if presidio-analyzer is installed
41
+
42
+ prompt_injection:
43
+ enabled: true
44
+ sensitivity: medium # low | medium | high
45
+ check_base64: true
46
+ llm_judge: false # Enable for high-security deployments (+latency)
47
+ log_attempts: true
48
+
49
+ topic_classifier:
50
+ enabled: false # Enable and configure allowed_topics for your use case
51
+ # allowed_topics:
52
+ # - customer_support
53
+ # - billing
54
+ # - product_info
55
+ # fallback_message: "I can only help with customer support, billing, and product topics."
56
+
57
+ toxicity_input:
58
+ enabled: false
59
+ # threshold: 0.8
60
+ # categories: [self_harm_promotion, violent_threats, dangerous_instructions]
61
+
62
+ rate_limiter:
63
+ enabled: true
64
+ requests_per_minute: 60
65
+ tokens_per_day: 100000
66
+ key_field: user_id # context field to key limits on
67
+ count_tokens: true
68
+
69
+ # ② PROCESSING GUARDRAILS (tool use / agent control)
70
+ processing:
71
+ tool_policy:
72
+ enabled: true
73
+ default_deny: true
74
+ default_role: user
75
+ approval_timeout: 30.0 # Seconds to wait for approval callback before denying
76
+ max_tool_calls_per_session: 0 # 0 = unlimited; set e.g. 50 to cap agentic loops
77
+ max_calls_per_tool: 0 # 0 = unlimited per-tool cap
78
+ # require_approval:
79
+ # - send_email
80
+ # - database_write
81
+ # - payment_*
82
+ # policies:
83
+ # user:
84
+ # allow: [search, calculator, fetch_url, read_file]
85
+ # deny: [file_write, exec_code, shell_command]
86
+ # argument_rules: # Argument-level constraints per tool
87
+ # read_file:
88
+ # path: "./data/*" # Only allow reads inside ./data/
89
+ # fetch_url:
90
+ # url: "https://*.trusted-domain.com/*"
91
+ # admin:
92
+ # allow: ["*"]
93
+ # deny: [shell_command]
94
+
95
+ context_control:
96
+ enabled: false # Not yet implemented
97
+ # max_rag_results: 5
98
+ # allowed_collections: [public_docs, kb_articles]
99
+
100
+ memory_hygiene:
101
+ enabled: false # Not yet implemented
102
+ # ttl_seconds: 3600
103
+ # max_memory_tokens: 4096
104
+
105
+ # ③ OUTPUT GUARDRAILS
106
+ output:
107
+ toxicity_output:
108
+ enabled: true
109
+ threshold: 0.7
110
+ action: block # block | warn | flag
111
+ categories:
112
+ - self_harm_promotion
113
+ - violent_threats
114
+ - dangerous_instructions
115
+ use_llm_judge: false # Enable for higher accuracy (+latency)
116
+
117
+ manipulation_output:
118
+ enabled: true
119
+ action: flag # flag | block; manipulation is contextual, measure before blocking
120
+ min_severity: medium # findings below it are recorded, never acted on
121
+ use_llm_judge: false # ClaudeJudge(mode="manipulation"), one model call per response
122
+
123
+ ai_disclosure_output:
124
+ enabled: true
125
+ action: flag # flag | redact | block
126
+ append_when: on_claim # never | on_claim | always
127
+
128
+ pii_restorer:
129
+ enabled: false # Enable when using PIIDetector(action="tokenize") on input
130
+ # Restores <PII:TYPE:N> tokens to original values after LLM response
131
+
132
+ hallucination:
133
+ enabled: false # Not yet implemented
134
+ # threshold: 0.6
135
+ # citation_required: false
136
+
137
+ schema_validator:
138
+ enabled: false # Not yet implemented
139
+ # schema: {}
140
+ # strict: false
141
+
142
+ content_policy:
143
+ enabled: false # Not yet implemented
144
+ # rules: []
145
+
146
+ # ④ POLICY COMPLIANCE
147
+ policy:
148
+ eu_ai_act:
149
+ enabled: true
150
+ risk_tier: limited # unacceptable | high | limited | minimal
151
+ system_id: my-ai-system
152
+ provider_name: My Organization
153
+ enable_audit_log: false # Set true for high-risk tier
154
+ audit_log_path: audit/eu_ai_act.jsonl
155
+ audit_retention_days: 365
156
+ check_prohibited: true
157
+ check_high_risk_indicators: true
158
+ strict_mode: true
159
+
160
+ gdpr:
161
+ enabled: false
162
+ # data_minimization: true
163
+ # purpose_limitation: true