contextwall 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 (66) hide show
  1. context_firewall/__init__.py +3 -0
  2. context_firewall/analytics/__init__.py +5 -0
  3. context_firewall/analytics/engine.py +234 -0
  4. context_firewall/api/__init__.py +5 -0
  5. context_firewall/api/app.py +1020 -0
  6. context_firewall/api/models.py +54 -0
  7. context_firewall/classifier/__init__.py +5 -0
  8. context_firewall/classifier/classifier.py +165 -0
  9. context_firewall/cli/__init__.py +5 -0
  10. context_firewall/cli/main.py +513 -0
  11. context_firewall/compliance/__init__.py +1 -0
  12. context_firewall/compliance/baa.py +57 -0
  13. context_firewall/compliance/chain.py +84 -0
  14. context_firewall/compliance/control_mappings.py +92 -0
  15. context_firewall/compliance/export.py +280 -0
  16. context_firewall/compliance/keys.py +94 -0
  17. context_firewall/config.py +234 -0
  18. context_firewall/control_plane/__init__.py +0 -0
  19. context_firewall/control_plane/client.py +107 -0
  20. context_firewall/control_plane/models.py +72 -0
  21. context_firewall/control_plane/pusher.py +377 -0
  22. context_firewall/daemon/__init__.py +5 -0
  23. context_firewall/daemon/main.py +461 -0
  24. context_firewall/db/__init__.py +6 -0
  25. context_firewall/db/connection.py +30 -0
  26. context_firewall/db/migrations.py +408 -0
  27. context_firewall/entropy/__init__.py +5 -0
  28. context_firewall/entropy/engine.py +271 -0
  29. context_firewall/graph/__init__.py +5 -0
  30. context_firewall/graph/engine.py +162 -0
  31. context_firewall/lint/__init__.py +0 -0
  32. context_firewall/lint/engine.py +334 -0
  33. context_firewall/mcp/__init__.py +5 -0
  34. context_firewall/mcp/server.py +237 -0
  35. context_firewall/metrics.py +100 -0
  36. context_firewall/models.py +130 -0
  37. context_firewall/policy/__init__.py +10 -0
  38. context_firewall/policy/detectors/__init__.py +0 -0
  39. context_firewall/policy/detectors/injection.py +480 -0
  40. context_firewall/policy/dsl/__init__.py +0 -0
  41. context_firewall/policy/dsl/evaluator.py +208 -0
  42. context_firewall/policy/dsl/loader.py +150 -0
  43. context_firewall/policy/dsl/types.py +112 -0
  44. context_firewall/policy/engine.py +532 -0
  45. context_firewall/provenance/__init__.py +5 -0
  46. context_firewall/provenance/engine.py +658 -0
  47. context_firewall/provenance/models.py +91 -0
  48. context_firewall/proxy/__init__.py +1 -0
  49. context_firewall/proxy/router.py +519 -0
  50. context_firewall/proxy/scanner.py +214 -0
  51. context_firewall/proxy/tokens.py +156 -0
  52. context_firewall/runtime/__init__.py +5 -0
  53. context_firewall/runtime/engine.py +303 -0
  54. context_firewall/source/__init__.py +1 -0
  55. context_firewall/source/registry.py +299 -0
  56. context_firewall/source/types.py +12 -0
  57. context_firewall/synthesizer/__init__.py +5 -0
  58. context_firewall/synthesizer/synthesizer.py +255 -0
  59. context_firewall/trust/__init__.py +5 -0
  60. context_firewall/trust/engine.py +139 -0
  61. context_firewall/trust/signals.py +184 -0
  62. contextwall-0.1.0.dist-info/METADATA +431 -0
  63. contextwall-0.1.0.dist-info/RECORD +66 -0
  64. contextwall-0.1.0.dist-info/WHEEL +4 -0
  65. contextwall-0.1.0.dist-info/entry_points.txt +3 -0
  66. contextwall-0.1.0.dist-info/licenses/LICENSE +33 -0
@@ -0,0 +1,54 @@
1
+ """REST API request/response Pydantic models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic import BaseModel
6
+
7
+ DEFAULT_TRUST_CUTOFF: float = 0.30
8
+
9
+
10
+ class AnalyzeOptions(BaseModel):
11
+ max_candidates: int = 20
12
+ trust_cutoff: float = DEFAULT_TRUST_CUTOFF
13
+
14
+
15
+ class AnalyzeRequest(BaseModel):
16
+ task: str
17
+ session_id: str | None = None
18
+ repository_root: str | None = None
19
+ options: AnalyzeOptions = AnalyzeOptions()
20
+
21
+
22
+ class BundleOptions(BaseModel):
23
+ token_budget: int | None = None
24
+ trust_cutoff: float = DEFAULT_TRUST_CUTOFF
25
+ include_summary: bool = True
26
+
27
+
28
+ class BundleRequest(BaseModel):
29
+ task: str
30
+ session_id: str | None = None
31
+ repository_root: str | None = None
32
+ options: BundleOptions = BundleOptions()
33
+
34
+
35
+ class OutcomeRequest(BaseModel):
36
+ session_id: str
37
+ request_id: str
38
+ outcome_type: str
39
+ success: bool
40
+ score: float
41
+ node_ids: list[str] = []
42
+ source_id: str = ""
43
+
44
+
45
+ class APIToken(BaseModel):
46
+ token: str
47
+ name: str
48
+ scopes: list[str]
49
+
50
+
51
+ class ErrorResponse(BaseModel):
52
+ error: str
53
+ code: str
54
+ request_id: str = ""
@@ -0,0 +1,5 @@
1
+ """Intent Classifier - wraps context-compiler classification with ContextWall extensions."""
2
+
3
+ from context_firewall.classifier.classifier import classify_task, build_pipeline_context
4
+
5
+ __all__ = ["classify_task", "build_pipeline_context"]
@@ -0,0 +1,165 @@
1
+ """Intent Classifier implementation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import time
7
+ import uuid
8
+ from datetime import datetime
9
+
10
+ from context_firewall.config import Config
11
+ from context_firewall.models import (
12
+ ClassificationResult,
13
+ PipelineContext,
14
+ TaskType,
15
+ TraversalStrategy,
16
+ )
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ _SECURITY_REVIEW_KEYWORDS = frozenset([
21
+ "security", "audit", "vulnerability", "cve", "exploit", "injection",
22
+ "xss", "csrf", "auth", "authentication", "authorization", "permission",
23
+ "sanitize", "validate input", "secret", "credential", "token leak",
24
+ ])
25
+
26
+ _DEPENDENCY_AUDIT_KEYWORDS = frozenset([
27
+ "dependency", "dependencies", "package", "import", "require",
28
+ "go.mod", "package.json", "requirements.txt", "sbom", "supply chain",
29
+ "license", "outdated", "upgrade package",
30
+ ])
31
+
32
+ _AUGMENTED_KEYWORDS: dict[TaskType, list[str]] = {
33
+ TaskType.SECURITY_REVIEW: [
34
+ "auth", "middleware", "token", "session", "permission", "sanitize", "validate",
35
+ ],
36
+ TaskType.DEPENDENCY_AUDIT: [
37
+ "import", "require", "go.mod", "package.json", "requirements.txt", "sbom",
38
+ ],
39
+ }
40
+
41
+ _TRAVERSAL_STRATEGIES: dict[TaskType, TraversalStrategy] = {
42
+ TaskType.BUG_FIX: TraversalStrategy(
43
+ edge_types=["calls", "imports"],
44
+ direction="both",
45
+ max_depth=4,
46
+ ),
47
+ TaskType.NEW_FEATURE: TraversalStrategy(
48
+ edge_types=["calls", "imports", "inherits"],
49
+ direction="both",
50
+ max_depth=4,
51
+ ),
52
+ TaskType.REFACTOR: TraversalStrategy(
53
+ edge_types=["calls", "imports", "inherits", "implements"],
54
+ direction="both",
55
+ max_depth=4,
56
+ ),
57
+ TaskType.SECURITY_REVIEW: TraversalStrategy(
58
+ edge_types=["calls", "imports", "uses"],
59
+ direction="inbound",
60
+ max_depth=3,
61
+ ),
62
+ TaskType.DEPENDENCY_AUDIT: TraversalStrategy(
63
+ edge_types=["imports", "requires"],
64
+ direction="outbound",
65
+ max_depth=2,
66
+ ),
67
+ }
68
+
69
+ _WEIGHT_PROFILES: dict[TaskType, str] = {
70
+ TaskType.BUG_FIX: "bug_fix",
71
+ TaskType.NEW_FEATURE: "new_feature",
72
+ TaskType.REFACTOR: "refactor",
73
+ TaskType.SECURITY_REVIEW: "security_review",
74
+ TaskType.DEPENDENCY_AUDIT: "dependency_audit",
75
+ }
76
+
77
+
78
+ def _detect_cre_extension(task: str) -> TaskType | None:
79
+ lower = task.lower()
80
+ security_hits = sum(1 for kw in _SECURITY_REVIEW_KEYWORDS if kw in lower)
81
+ dependency_hits = sum(1 for kw in _DEPENDENCY_AUDIT_KEYWORDS if kw in lower)
82
+ if security_hits >= 2:
83
+ return TaskType.SECURITY_REVIEW
84
+ if dependency_hits >= 2:
85
+ return TaskType.DEPENDENCY_AUDIT
86
+ return None
87
+
88
+
89
+ def _classify_via_context_compiler(task: str) -> ClassificationResult:
90
+ try:
91
+ from context_compiler.retrieval.classifier import classify, extract_query_keywords
92
+ from context_compiler.models import TaskType as CCTaskType
93
+
94
+ cc_task_type = classify(task)
95
+ keywords = extract_query_keywords(task)
96
+ task_type_map = {
97
+ "BUG_FIX": TaskType.BUG_FIX,
98
+ "NEW_FEATURE": TaskType.NEW_FEATURE,
99
+ "REFACTOR": TaskType.REFACTOR,
100
+ }
101
+ task_type = task_type_map.get(cc_task_type.value, TaskType.NEW_FEATURE)
102
+ return ClassificationResult(
103
+ task_type=task_type,
104
+ confidence=1.0,
105
+ keywords=list(keywords),
106
+ source="context-compiler",
107
+ )
108
+ except Exception as e:
109
+ logger.warning("context-compiler classify failed, using fallback", extra={"error": str(e)})
110
+ return ClassificationResult(
111
+ task_type=TaskType.NEW_FEATURE,
112
+ confidence=0.0,
113
+ keywords=[],
114
+ source="fallback",
115
+ )
116
+
117
+
118
+ def classify_task(task: str) -> ClassificationResult:
119
+ t0 = time.monotonic()
120
+
121
+ cre_type = _detect_cre_extension(task)
122
+ if cre_type is not None:
123
+ augmented = _AUGMENTED_KEYWORDS.get(cre_type, [])
124
+ result = ClassificationResult(
125
+ task_type=cre_type,
126
+ confidence=1.0,
127
+ keywords=augmented,
128
+ source="cre-extension",
129
+ )
130
+ else:
131
+ result = _classify_via_context_compiler(task)
132
+ augmented = _AUGMENTED_KEYWORDS.get(result.task_type, [])
133
+ if augmented:
134
+ result = result.model_copy(update={"keywords": result.keywords + augmented})
135
+
136
+ elapsed_ms = (time.monotonic() - t0) * 1000
137
+ logger.debug("classify_task", extra={"task_type": result.task_type, "latency_ms": elapsed_ms})
138
+ return result
139
+
140
+
141
+ def build_pipeline_context(
142
+ task: str,
143
+ classification: ClassificationResult,
144
+ session_id: str,
145
+ config: Config,
146
+ ) -> PipelineContext:
147
+ strategy = _TRAVERSAL_STRATEGIES.get(
148
+ classification.task_type,
149
+ TraversalStrategy(edge_types=["calls", "imports"], direction="both", max_depth=4),
150
+ )
151
+ # respect config depth override
152
+ if config.graph.max_depth != 4:
153
+ strategy = strategy.model_copy(update={"max_depth": config.graph.max_depth})
154
+
155
+ return PipelineContext(
156
+ task=task,
157
+ task_type=classification.task_type,
158
+ confidence=classification.confidence,
159
+ keywords=classification.keywords,
160
+ traversal_strategy=strategy,
161
+ trust_weight_profile=_WEIGHT_PROFILES.get(classification.task_type, "new_feature"),
162
+ request_id=str(uuid.uuid4()),
163
+ session_id=session_id,
164
+ received_at=datetime.utcnow(),
165
+ )
@@ -0,0 +1,5 @@
1
+ """Click CLI - ctxfw command."""
2
+
3
+ from context_firewall.cli.main import cli
4
+
5
+ __all__ = ["cli"]