sourcecode 2.4.0__py3-none-any.whl → 2.5.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.
- sourcecode/__init__.py +1 -1
- sourcecode/archetype.py +46 -0
- sourcecode/cli.py +429 -3
- sourcecode/context_graph.py +32 -24
- sourcecode/repository_ir.py +1 -1
- sourcecode/retrieval/__init__.py +192 -0
- sourcecode/retrieval/context.py +241 -0
- sourcecode/retrieval/errors.py +41 -0
- sourcecode/retrieval/executor.py +51 -0
- sourcecode/retrieval/planner.py +297 -0
- sourcecode/retrieval/query.py +484 -0
- sourcecode/retrieval/request.py +94 -0
- sourcecode/retrieval/resolution.py +135 -0
- sourcecode/retrieval/result.py +144 -0
- sourcecode/retrieval/retriever.py +62 -0
- sourcecode/retrieval/runtime.py +259 -0
- sourcecode/retrieval/steps.py +242 -0
- sourcecode/retrieval/steps_endpoint.py +311 -0
- sourcecode/retrieval/steps_graph.py +248 -0
- sourcecode/retrieval/steps_impact.py +293 -0
- sourcecode/retrieval/steps_intf.py +247 -0
- sourcecode/retrieval/steps_struct.py +338 -0
- sourcecode/retrieval/steps_txsec.py +351 -0
- sourcecode/security_config.py +4 -4
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.0.dist-info}/METADATA +4 -4
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.0.dist-info}/RECORD +29 -11
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.0.dist-info}/WHEEL +0 -0
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.0.dist-info}/entry_points.txt +0 -0
- {sourcecode-2.4.0.dist-info → sourcecode-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"""TRANSACTIONS & SECURITY pack step handlers (Fase 6).
|
|
2
|
+
|
|
3
|
+
Six intents (TRANSACTION_FLOW, TRANSACTION_ENTRYPOINTS, TRANSACTION_PROPAGATION,
|
|
4
|
+
SECURITY_SURFACE, SECURITY_CHAIN, VALIDATION_POINTS) expressed purely as compositions of
|
|
5
|
+
these projection steps. NO new analyzer: every step reuses an existing engine and projects
|
|
6
|
+
its already-computed output.
|
|
7
|
+
|
|
8
|
+
* Transactions → `SpringSemanticModel.tx_index` (structural boundaries) + `run_tx_audit`.
|
|
9
|
+
* Security → `run_security_audit` (+ the endpoint model for scoping).
|
|
10
|
+
* Validation → `build_validation_surface`.
|
|
11
|
+
|
|
12
|
+
No step opens source or parses: the ContextGraph / SpringSemanticModel are acquired once by
|
|
13
|
+
the shared `KnowledgeContext`; steps only read them. Ordering is deterministic; ranking
|
|
14
|
+
reuses the engines' own severity/confidence (`spring_findings.SEVERITY_ORDER`).
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
from sourcecode.spring_findings import SEVERITY_ORDER
|
|
21
|
+
from sourcecode.retrieval.query import (
|
|
22
|
+
CollectSecurityEvidence,
|
|
23
|
+
RankByCriticality,
|
|
24
|
+
ResolvePropagation,
|
|
25
|
+
ResolveSecurityChain,
|
|
26
|
+
ResolveSecuritySurface,
|
|
27
|
+
ResolveTransactionEntrypoints,
|
|
28
|
+
ResolveTransactionFlow,
|
|
29
|
+
ResolveValidationPoints,
|
|
30
|
+
Step,
|
|
31
|
+
)
|
|
32
|
+
from sourcecode.retrieval.result import (
|
|
33
|
+
Explanation,
|
|
34
|
+
KnowledgeEntity,
|
|
35
|
+
Observation,
|
|
36
|
+
Provenance,
|
|
37
|
+
RetrievalEvidence,
|
|
38
|
+
)
|
|
39
|
+
from sourcecode.retrieval.steps import (
|
|
40
|
+
SLOT_CONFIDENCE,
|
|
41
|
+
SLOT_ENTITIES,
|
|
42
|
+
SLOT_EVIDENCE,
|
|
43
|
+
SLOT_EXPLANATION,
|
|
44
|
+
SLOT_OBSERVATIONS,
|
|
45
|
+
SLOT_PROVENANCE,
|
|
46
|
+
)
|
|
47
|
+
from sourcecode.retrieval.steps_impact import SLOT_TARGET
|
|
48
|
+
|
|
49
|
+
if TYPE_CHECKING:
|
|
50
|
+
from sourcecode.retrieval.runtime import StepContext, StepRegistry
|
|
51
|
+
|
|
52
|
+
SLOT_SERVICES = "txsec_services"
|
|
53
|
+
_PROPAGATION_PATTERNS = frozenset({"TX-002", "TX-003", "TX-004"})
|
|
54
|
+
_CONF_RANK = {"high": 0, "medium": 1, "low": 2}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# ── transactions (structural: SpringSemanticModel.tx_index) ──────────────────────
|
|
58
|
+
def resolve_transaction_flow(step: Step, ctx: "StepContext") -> None:
|
|
59
|
+
assert isinstance(step, ResolveTransactionFlow)
|
|
60
|
+
tx = ctx.knowledge.spring_model.tx_index
|
|
61
|
+
boundaries = list(tx.all_declared)
|
|
62
|
+
ctx.put(SLOT_ENTITIES, [_boundary_entity(b, "transaction_boundary") for b in boundaries])
|
|
63
|
+
ctx.put(SLOT_EVIDENCE, [_boundary_evidence(b) for b in boundaries])
|
|
64
|
+
ctx.put(SLOT_OBSERVATIONS, _stats_observations(tx))
|
|
65
|
+
ctx.put(SLOT_CONFIDENCE, _agg_conf([b.confidence for b in boundaries]))
|
|
66
|
+
_add_service(ctx, "SpringSemanticModel")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def resolve_transaction_entrypoints(step: Step, ctx: "StepContext") -> None:
|
|
70
|
+
"""Transactional boundaries whose enclosing class is a controller — where transactions
|
|
71
|
+
begin at the API surface. Reuses tx_index × the endpoint model's controller set."""
|
|
72
|
+
assert isinstance(step, ResolveTransactionEntrypoints)
|
|
73
|
+
model = ctx.knowledge.spring_model
|
|
74
|
+
controllers = set(model.endpoint_index.controller_fqns)
|
|
75
|
+
boundaries = [b for b in model.tx_index.all_declared if _enclosing_class(b.symbol) in controllers]
|
|
76
|
+
ctx.put(SLOT_ENTITIES, [_boundary_entity(b, "transaction_entrypoint") for b in boundaries])
|
|
77
|
+
ctx.put(SLOT_EVIDENCE, [_boundary_evidence(b) for b in boundaries])
|
|
78
|
+
ctx.put(SLOT_CONFIDENCE, _agg_conf([b.confidence for b in boundaries]))
|
|
79
|
+
_add_service(ctx, "SpringSemanticModel")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def resolve_propagation(step: Step, ctx: "StepContext") -> None:
|
|
83
|
+
"""Boundaries with non-default propagation + the propagation-risk tx audit findings.
|
|
84
|
+
Reuses tx_index + `run_tx_audit`."""
|
|
85
|
+
assert isinstance(step, ResolvePropagation)
|
|
86
|
+
from sourcecode.spring_tx_analyzer import run_tx_audit
|
|
87
|
+
|
|
88
|
+
model = ctx.knowledge.spring_model
|
|
89
|
+
non_default = [b for b in model.tx_index.all_declared if b.propagation != "REQUIRED"]
|
|
90
|
+
findings = [
|
|
91
|
+
f
|
|
92
|
+
for f in run_tx_audit(
|
|
93
|
+
ctx.knowledge.context_graph.cir, root=ctx.knowledge.root, model=model
|
|
94
|
+
).findings
|
|
95
|
+
if f.pattern_id in _PROPAGATION_PATTERNS
|
|
96
|
+
]
|
|
97
|
+
ctx.put(SLOT_ENTITIES, [_boundary_entity(b, "propagation_point") for b in non_default])
|
|
98
|
+
ctx.put(SLOT_EVIDENCE, [_boundary_evidence(b) for b in non_default] + [_finding_evidence(f) for f in findings])
|
|
99
|
+
ctx.put(SLOT_OBSERVATIONS, _stats_observations(model.tx_index))
|
|
100
|
+
ctx.put(SLOT_CONFIDENCE, _agg_conf([b.confidence for b in non_default] + [f.confidence for f in findings]))
|
|
101
|
+
_add_service(ctx, "SpringSemanticModel")
|
|
102
|
+
_add_service(ctx, "run_tx_audit")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# ── security (reuse run_security_audit) ──────────────────────────────────────────
|
|
106
|
+
def resolve_security_surface(step: Step, ctx: "StepContext") -> None:
|
|
107
|
+
assert isinstance(step, ResolveSecuritySurface)
|
|
108
|
+
findings = _security_findings(ctx)
|
|
109
|
+
ctx.put(SLOT_ENTITIES, [_finding_entity(f) for f in findings])
|
|
110
|
+
ctx.put(SLOT_EVIDENCE, [_finding_evidence(f) for f in findings])
|
|
111
|
+
ctx.put(SLOT_OBSERVATIONS, _severity_observations(findings))
|
|
112
|
+
ctx.put(SLOT_CONFIDENCE, _agg_conf([f.confidence for f in findings]))
|
|
113
|
+
_add_service(ctx, "run_security_audit")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def resolve_security_chain(step: Step, ctx: "StepContext") -> None:
|
|
117
|
+
"""Security findings scoped to a target (symbol / related / enclosing class). Reuses
|
|
118
|
+
`run_security_audit`; the target comes from the shared ResolveTarget step."""
|
|
119
|
+
assert isinstance(step, ResolveSecurityChain)
|
|
120
|
+
target = ctx.require(SLOT_TARGET)
|
|
121
|
+
scoped = [f for f in _security_findings(ctx) if _touches(f, target)]
|
|
122
|
+
ctx.put(SLOT_ENTITIES, [_finding_entity(f) for f in scoped])
|
|
123
|
+
ctx.put(SLOT_EVIDENCE, [_finding_evidence(f) for f in scoped])
|
|
124
|
+
ctx.put(SLOT_OBSERVATIONS, _severity_observations(scoped))
|
|
125
|
+
ctx.put(SLOT_CONFIDENCE, _agg_conf([f.confidence for f in scoped]))
|
|
126
|
+
_add_service(ctx, "run_security_audit")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# ── validation (reuse build_validation_surface) ──────────────────────────────────
|
|
130
|
+
def resolve_validation_points(step: Step, ctx: "StepContext") -> None:
|
|
131
|
+
assert isinstance(step, ResolveValidationPoints)
|
|
132
|
+
from sourcecode.validation_surface import build_validation_surface
|
|
133
|
+
|
|
134
|
+
surface = build_validation_surface(ctx.knowledge.root, graph=ctx.knowledge.context_graph)
|
|
135
|
+
endpoints = surface.get("endpoints", []) or []
|
|
136
|
+
gaps = surface.get("gaps", []) or []
|
|
137
|
+
entities = [
|
|
138
|
+
KnowledgeEntity(
|
|
139
|
+
identity=_route_id(ep),
|
|
140
|
+
kind="validation_point",
|
|
141
|
+
score=0.0,
|
|
142
|
+
attributes={k: v for k, v in ep.items() if k not in ("source_file", "line")},
|
|
143
|
+
)
|
|
144
|
+
for ep in endpoints
|
|
145
|
+
] + [
|
|
146
|
+
KnowledgeEntity(identity=_route_id(g), kind="validation_gap", score=0.0, attributes=dict(g))
|
|
147
|
+
for g in gaps
|
|
148
|
+
]
|
|
149
|
+
ctx.put(SLOT_ENTITIES, entities)
|
|
150
|
+
ctx.put(
|
|
151
|
+
SLOT_EVIDENCE,
|
|
152
|
+
[
|
|
153
|
+
RetrievalEvidence(
|
|
154
|
+
signal="validation",
|
|
155
|
+
detail=_route_id(ep),
|
|
156
|
+
weight=1.0,
|
|
157
|
+
strength=1.0,
|
|
158
|
+
mass=1.0,
|
|
159
|
+
contribution=1.0,
|
|
160
|
+
provider="build_validation_surface",
|
|
161
|
+
source_file=ep.get("source_file"),
|
|
162
|
+
source_line=ep.get("line"),
|
|
163
|
+
)
|
|
164
|
+
for ep in endpoints
|
|
165
|
+
],
|
|
166
|
+
)
|
|
167
|
+
summary = surface.get("summary", {}) or {}
|
|
168
|
+
ctx.put(
|
|
169
|
+
SLOT_OBSERVATIONS,
|
|
170
|
+
[Observation(name=str(k), value=v, detail="validation surface summary") for k, v in summary.items()],
|
|
171
|
+
)
|
|
172
|
+
ctx.put(SLOT_CONFIDENCE, "high" if endpoints or gaps else "medium")
|
|
173
|
+
_add_service(ctx, "build_validation_surface")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# ── ranking + terminal evidence (generic across the pack) ────────────────────────
|
|
177
|
+
def rank_by_criticality(step: Step, ctx: "StepContext") -> None:
|
|
178
|
+
"""Order entities by the engines' OWN severity then confidence then identity. No new
|
|
179
|
+
score is computed — SEVERITY_ORDER is the audit engines' own severity ranking."""
|
|
180
|
+
assert isinstance(step, RankByCriticality)
|
|
181
|
+
entities = ctx.get(SLOT_ENTITIES, [])
|
|
182
|
+
|
|
183
|
+
def key(e: KnowledgeEntity):
|
|
184
|
+
sev = SEVERITY_ORDER.get(e.attributes.get("severity"), 9)
|
|
185
|
+
conf = _CONF_RANK.get(e.attributes.get("confidence"), 9)
|
|
186
|
+
return (sev, conf, e.identity)
|
|
187
|
+
|
|
188
|
+
ctx.put(SLOT_ENTITIES, sorted(entities, key=key))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def collect_security_evidence(step: Step, ctx: "StepContext") -> None:
|
|
192
|
+
"""Assemble confidence, structured explanation (no synthesized prose), and provenance
|
|
193
|
+
from what the resolve steps produced. GENERIC across every tx/security intent."""
|
|
194
|
+
confidence = ctx.get(SLOT_CONFIDENCE, "medium")
|
|
195
|
+
ctx.put(
|
|
196
|
+
SLOT_EXPLANATION,
|
|
197
|
+
Explanation(
|
|
198
|
+
winner=None,
|
|
199
|
+
score=0.0,
|
|
200
|
+
confidence=confidence,
|
|
201
|
+
top_contributions=(),
|
|
202
|
+
runner_up=None,
|
|
203
|
+
engine_explanation="",
|
|
204
|
+
),
|
|
205
|
+
)
|
|
206
|
+
ctx.put(
|
|
207
|
+
SLOT_PROVENANCE,
|
|
208
|
+
Provenance(
|
|
209
|
+
services=tuple(ctx.get(SLOT_SERVICES, [])),
|
|
210
|
+
signals_used=("tx_index", "endpoint_index", "security_audit", "validation_surface"),
|
|
211
|
+
signals_missing=(),
|
|
212
|
+
knowledge_source="SpringSemanticModel + audit/validation engines",
|
|
213
|
+
),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ── helpers ──────────────────────────────────────────────────────────────────────
|
|
218
|
+
def _security_findings(ctx: "StepContext") -> list:
|
|
219
|
+
from sourcecode.spring_security_audit import run_security_audit
|
|
220
|
+
|
|
221
|
+
return run_security_audit(
|
|
222
|
+
ctx.knowledge.context_graph.cir, root=ctx.knowledge.root, model=ctx.knowledge.spring_model
|
|
223
|
+
).findings
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _boundary_entity(b, kind: str) -> KnowledgeEntity:
|
|
227
|
+
return KnowledgeEntity(
|
|
228
|
+
identity=b.symbol,
|
|
229
|
+
kind=kind,
|
|
230
|
+
score=0.0,
|
|
231
|
+
attributes={
|
|
232
|
+
"scope": b.scope,
|
|
233
|
+
"propagation": b.propagation,
|
|
234
|
+
"isolation": b.isolation,
|
|
235
|
+
"read_only": b.read_only,
|
|
236
|
+
"proxy_bypass_risk": b.is_proxy_bypass_risk,
|
|
237
|
+
"confidence": b.confidence,
|
|
238
|
+
},
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _boundary_evidence(b) -> RetrievalEvidence:
|
|
243
|
+
return RetrievalEvidence(
|
|
244
|
+
signal="transactional",
|
|
245
|
+
detail=f"@Transactional({b.propagation}, readOnly={b.read_only})",
|
|
246
|
+
weight=1.0,
|
|
247
|
+
strength=1.0,
|
|
248
|
+
mass=1.0,
|
|
249
|
+
contribution=1.0,
|
|
250
|
+
provider="SpringSemanticModel",
|
|
251
|
+
source_file=b.source_file or None,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _finding_entity(f) -> KnowledgeEntity:
|
|
256
|
+
return KnowledgeEntity(
|
|
257
|
+
identity=f.symbol,
|
|
258
|
+
kind="security_finding",
|
|
259
|
+
score=0.0,
|
|
260
|
+
attributes={
|
|
261
|
+
"pattern_id": f.pattern_id,
|
|
262
|
+
"severity": f.severity,
|
|
263
|
+
"confidence": f.confidence,
|
|
264
|
+
"title": f.title,
|
|
265
|
+
},
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _finding_evidence(f) -> RetrievalEvidence:
|
|
270
|
+
file = line = None
|
|
271
|
+
sf = getattr(f, "source_file", "") or ""
|
|
272
|
+
if sf:
|
|
273
|
+
file = sf
|
|
274
|
+
return RetrievalEvidence(
|
|
275
|
+
signal=f.pattern_id,
|
|
276
|
+
detail=f.title,
|
|
277
|
+
weight=1.0,
|
|
278
|
+
strength=1.0,
|
|
279
|
+
mass=1.0,
|
|
280
|
+
contribution=1.0,
|
|
281
|
+
provider=f"audit:{f.category}",
|
|
282
|
+
source_file=file,
|
|
283
|
+
source_line=line,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _stats_observations(tx) -> list:
|
|
288
|
+
stats = tx.stats() if hasattr(tx, "stats") else {}
|
|
289
|
+
out = []
|
|
290
|
+
for k, v in stats.items():
|
|
291
|
+
if isinstance(v, dict):
|
|
292
|
+
out.append(Observation(name=k, value=sum(v.values()), detail=f"{k}: {v}"))
|
|
293
|
+
else:
|
|
294
|
+
out.append(Observation(name=str(k), value=v, detail="tx_index stats"))
|
|
295
|
+
return out
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _severity_observations(findings) -> list:
|
|
299
|
+
hist: dict[str, int] = {}
|
|
300
|
+
for f in findings:
|
|
301
|
+
hist[f.severity] = hist.get(f.severity, 0) + 1
|
|
302
|
+
return [Observation(name=f"severity_{s}", value=n, detail="security finding count") for s, n in sorted(hist.items())]
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def _route_id(d: dict) -> str:
|
|
306
|
+
return (
|
|
307
|
+
d.get("route")
|
|
308
|
+
or d.get("path")
|
|
309
|
+
or f"{d.get('method', '')} {d.get('handler', '')}".strip()
|
|
310
|
+
or d.get("handler", "")
|
|
311
|
+
or "?"
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _touches(f, target: str) -> bool:
|
|
316
|
+
return (
|
|
317
|
+
f.symbol == target
|
|
318
|
+
or target in (getattr(f, "related_symbols", []) or [])
|
|
319
|
+
or _enclosing_class(f.symbol) == target
|
|
320
|
+
or f.symbol.startswith(target)
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def _enclosing_class(symbol: str) -> str:
|
|
325
|
+
return symbol.split("#", 1)[0]
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def _agg_conf(confs) -> str:
|
|
329
|
+
ranked = [c for c in confs if c in _CONF_RANK]
|
|
330
|
+
if not ranked:
|
|
331
|
+
return "high"
|
|
332
|
+
return max(ranked, key=lambda c: _CONF_RANK[c]) # most conservative (lowest)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _add_service(ctx: "StepContext", name: str) -> None:
|
|
336
|
+
services = list(ctx.get(SLOT_SERVICES, []))
|
|
337
|
+
if name not in services:
|
|
338
|
+
services.append(name)
|
|
339
|
+
ctx.put(SLOT_SERVICES, services)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def register_txsec_steps(registry: "StepRegistry") -> None:
|
|
343
|
+
"""Register the TRANSACTIONS & SECURITY handlers (the sanctioned extension seam)."""
|
|
344
|
+
registry.register(ResolveTransactionFlow.kind, resolve_transaction_flow)
|
|
345
|
+
registry.register(ResolveTransactionEntrypoints.kind, resolve_transaction_entrypoints)
|
|
346
|
+
registry.register(ResolvePropagation.kind, resolve_propagation)
|
|
347
|
+
registry.register(ResolveSecuritySurface.kind, resolve_security_surface)
|
|
348
|
+
registry.register(ResolveSecurityChain.kind, resolve_security_chain)
|
|
349
|
+
registry.register(ResolveValidationPoints.kind, resolve_validation_points)
|
|
350
|
+
registry.register(RankByCriticality.kind, rank_by_criticality)
|
|
351
|
+
registry.register(CollectSecurityEvidence.kind, collect_security_evidence)
|
sourcecode/security_config.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Custom security annotation configuration (BUG-3).
|
|
2
2
|
|
|
3
3
|
Enterprise Spring projects routinely guard endpoints with bespoke authorization
|
|
4
|
-
annotations (e.g. ``@
|
|
4
|
+
annotations (e.g. ``@CustomSecurityAnnotation(nombreRecurso=..., nivelRequerido=...)``)
|
|
5
5
|
instead of the standard ``@PreAuthorize`` / ``@Secured`` set. Without knowing
|
|
6
6
|
those names, the endpoint surface reports ``policy: none_detected`` for every
|
|
7
7
|
protected route, which makes ``endpoints`` / ``spring-audit`` blind in exactly
|
|
@@ -18,8 +18,8 @@ Config shape::
|
|
|
18
18
|
{
|
|
19
19
|
"customSecurityAnnotations": [
|
|
20
20
|
{
|
|
21
|
-
"fullyQualifiedName": "com.example.security.
|
|
22
|
-
"shortName": "
|
|
21
|
+
"fullyQualifiedName": "com.example.security.CustomSecurityAnnotation",
|
|
22
|
+
"shortName": "CustomSecurityAnnotation",
|
|
23
23
|
"resourceParam": "nombreRecurso",
|
|
24
24
|
"levelParam": "nivelRequerido",
|
|
25
25
|
"riskLevel": "custom"
|
|
@@ -41,7 +41,7 @@ CONFIG_FILENAME = "sourcecode.config.json"
|
|
|
41
41
|
class CustomSecuritySpec:
|
|
42
42
|
"""One custom security annotation the analyzer should recognize."""
|
|
43
43
|
|
|
44
|
-
short_name: str # e.g. "
|
|
44
|
+
short_name: str # e.g. "CustomSecurityAnnotation" (no leading @)
|
|
45
45
|
fqn: str = "" # fully-qualified name (optional)
|
|
46
46
|
resource_param: str = "" # annotation attribute naming the protected resource
|
|
47
47
|
level_param: str = "" # annotation attribute naming the required level
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Keywords: agents,ai,codebase,context,developer-tools,llm
|
|
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
|
|
|
42
42
|
|
|
43
43
|
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
44
44
|
|
|
45
|
-

|
|
46
46
|

|
|
47
47
|
|
|
48
48
|
> **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
|
|
@@ -84,7 +84,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
84
84
|
# pip / pipx
|
|
85
85
|
pipx install sourcecode # or: pip install sourcecode
|
|
86
86
|
|
|
87
|
-
ask version # ask 2.
|
|
87
|
+
ask version # ask 2.5.0
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
> **Package vs. command.** The install package is named `sourcecode` this release
|
|
@@ -218,7 +218,7 @@ repo root (otherwise they report `policy: "none_detected"`):
|
|
|
218
218
|
```json
|
|
219
219
|
{
|
|
220
220
|
"customSecurityAnnotations": [
|
|
221
|
-
{ "fullyQualifiedName": "com.example.security.
|
|
221
|
+
{ "fullyQualifiedName": "com.example.security.CustomSecurityAnnotation", "shortName": "CustomSecurityAnnotation" }
|
|
222
222
|
]
|
|
223
223
|
}
|
|
224
224
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=wPl09nh67L2BWCogYMSS9J9rk7fRv2rZc1D97h9pLNU,308
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=XffluXKzJUXrMtjEiAOnSNPZnztdIcts17T9ouHeID0,10521
|
|
3
|
-
sourcecode/archetype.py,sha256=
|
|
3
|
+
sourcecode/archetype.py,sha256=d7yoN6Tj4OBj-VgSMPEKg4WF9H8FypnZ5A6AkUh5oIE,34484
|
|
4
4
|
sourcecode/architecture_analyzer.py,sha256=6_wC4TYuBYxaqckZS0I1vBSMRPeH2vzlDB48gXwOOd4,46627
|
|
5
5
|
sourcecode/architecture_summary.py,sha256=pkl6lIOnSy-poa9EzW43U0MkXhx2FDfAFh8pDXLpcTo,26630
|
|
6
6
|
sourcecode/ast_extractor.py,sha256=FEsYTsMCXbJfSYQZRk1k-I-PjUNGnKqO1IxMftsgA5U,51351
|
|
@@ -10,11 +10,11 @@ sourcecode/caller_metrics.py,sha256=HG8RCOkpzzsEGdnMRob6byrwjoj5__t0TEsBj4yR7ks,
|
|
|
10
10
|
sourcecode/canonical_ir.py,sha256=U69m8Vkr0p407xF1q5y1KguHXWEAubYw8NFHR9hDNJk,29178
|
|
11
11
|
sourcecode/cir_graphs.py,sha256=9G0HHj1kw2325IDyzo2OpX73BNswEckecf4MZUXB4JM,12078
|
|
12
12
|
sourcecode/classifier.py,sha256=RhLMDR031FAiUcT3bsf2EL3KrFwl7KsWh_wXXR_Bumo,18729
|
|
13
|
-
sourcecode/cli.py,sha256=
|
|
13
|
+
sourcecode/cli.py,sha256=46Chp0JsEWD_j0HUWOx4tOhrsXSWgWV8JhL5G8SyW4I,322078
|
|
14
14
|
sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
|
|
15
15
|
sourcecode/confidence_analyzer.py,sha256=_jckZSxksV-OU38vbkxfVNBnWCtlCq8Vwfg23x1uspA,19054
|
|
16
16
|
sourcecode/context_cache.py,sha256=maws79rLKDwyZ7c9Q2LwlIxqZHRFlaKzErtO3mglWoA,25036
|
|
17
|
-
sourcecode/context_graph.py,sha256=
|
|
17
|
+
sourcecode/context_graph.py,sha256=WFtUvfxoE8XtQxtRJLvaF4SJuS00ICjNoTk0sH2_V5U,44454
|
|
18
18
|
sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
|
|
19
19
|
sourcecode/context_summarizer.py,sha256=cI2TZMvEhl0BEma12VtPaX6z03ZVBAetVzuK5GaCOvg,6852
|
|
20
20
|
sourcecode/contract_model.py,sha256=nRxJKPMs1VHwFTa8AVXhGmaLjti3Lr2sjHDpWgv1bfE,3917
|
|
@@ -55,12 +55,12 @@ sourcecode/redactor.py,sha256=SB4hwIvg8h-hvcqKcDWaZvA-aSyn-at-BIRwa0tUv5E,3227
|
|
|
55
55
|
sourcecode/relevance_scorer.py,sha256=0AgEt4KrV73nioMqBgjhGjtY7L2C7L7cSyKtj3IKcrw,9408
|
|
56
56
|
sourcecode/rename_refactor.py,sha256=h6dNFlB9aZ_3q6heeHBkgXQeXaT03nvPSsYH6P8qxFg,12965
|
|
57
57
|
sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
|
|
58
|
-
sourcecode/repository_ir.py,sha256=
|
|
58
|
+
sourcecode/repository_ir.py,sha256=YhsefuP7tyn5VyoWwBmqu4nIZw4MJ7y0wzt9K1xviqY,284202
|
|
59
59
|
sourcecode/ris.py,sha256=aG2D4159gtpg968yD3PylYbIXhGFOwIlFBI0DSr84yY,20412
|
|
60
60
|
sourcecode/runtime_classifier.py,sha256=uTAD6BDCiBLUZEDRfqk718kM4RTT_vAbfkcOI2_Xx58,18432
|
|
61
61
|
sourcecode/scanner.py,sha256=WdOQ78mMzjR1NjmKTlbxdgwinnCTfAhxCVLBEFQiFHU,8899
|
|
62
62
|
sourcecode/schema.py,sha256=aHNXDf8LGyUC8ZDE_VS9kiskC2-Oswhi_WnpdGy6HDw,24897
|
|
63
|
-
sourcecode/security_config.py,sha256=
|
|
63
|
+
sourcecode/security_config.py,sha256=KblMEoRiEjrIE68YsPaUAFebxFp8UM7MS7lAk5CGD8U,3531
|
|
64
64
|
sourcecode/security_posture.py,sha256=CAJw4oJD0aAW2yRewvd_fonkzi9_HpUjBZlIDZle00s,26034
|
|
65
65
|
sourcecode/semantic_analyzer.py,sha256=bpgdC6m0_ftVtRf3rSdwhbhWjnZnGxRXaZVcfe4BbcQ,95414
|
|
66
66
|
sourcecode/semantic_impact_engine.py,sha256=HpgjenY6DLPHPomP7Hw850zA-EBokf1S4O2sh8NegdI,20351
|
|
@@ -112,14 +112,32 @@ sourcecode/mcp/onboarding/applier.py,sha256=Z2ZqzPh7dTTzT7tfxDbfjDJKiBNQ18CPQCaR
|
|
|
112
112
|
sourcecode/mcp/onboarding/backup.py,sha256=ihqGOR8QTX8HASRSEDyfFyXr5bkXrygPHamv4p9KTmk,1452
|
|
113
113
|
sourcecode/mcp/onboarding/detector.py,sha256=kDc0U6kXMuq_GivqwKrgJzIVLVeoLr3RQl63ksW10I8,3327
|
|
114
114
|
sourcecode/mcp/onboarding/planner.py,sha256=Fopg5f72FDiPfldF7NOxYjcBA_w8hi_jBJpSz39lPb8,1332
|
|
115
|
+
sourcecode/retrieval/__init__.py,sha256=h5pKDzXOlu_NQy-YxOaqMSD6UDNoYsmsYSoNLRRZ5uM,5478
|
|
116
|
+
sourcecode/retrieval/context.py,sha256=hjm_RxReZar6GZvVVg4XNR9sVMOUuilbi1Jt7iUoerU,11116
|
|
117
|
+
sourcecode/retrieval/errors.py,sha256=U-zqxzlzCWe3NYCNOBASTSPn1xS8j9D7LfwpGBiznL4,1452
|
|
118
|
+
sourcecode/retrieval/executor.py,sha256=H2-5by5UCYgX7lgJtmT8JJ73ldxp6xiBFEf6r__j_XA,2048
|
|
119
|
+
sourcecode/retrieval/planner.py,sha256=9DPoutVHEYaGodDTmihZjqeNS6vFwJKtANnmO-4cvlU,13375
|
|
120
|
+
sourcecode/retrieval/query.py,sha256=QoVKsuV-PYuunbw06MvV_HdHLAKbo_r-S9xEWFoAVB4,18406
|
|
121
|
+
sourcecode/retrieval/request.py,sha256=gKK5iL5X7ScMz_HQ53FX4G6lbFdkhh0vNkIuxGDLt74,4023
|
|
122
|
+
sourcecode/retrieval/resolution.py,sha256=boa9ybj3AQK5CEMYJn9jA8e0XRNyKKD9avRM5JAIwyA,7163
|
|
123
|
+
sourcecode/retrieval/result.py,sha256=mx6ioA6y6bkNbF6SC3n0N99NTuNEy1uz_5YZQ2euflA,4726
|
|
124
|
+
sourcecode/retrieval/retriever.py,sha256=YdnbaXaWhFKyShuuE6fj36GfgpuGetqOFzx7_D2A9CY,2654
|
|
125
|
+
sourcecode/retrieval/runtime.py,sha256=ODQlPqyS4OfMtCb1oEA_0t7vK0uKPBLhB4K2CnytPUU,10822
|
|
126
|
+
sourcecode/retrieval/steps.py,sha256=wyOiO84fuDgdd-HdugzGSEriN-lN891PTc3gU7lgcmI,9959
|
|
127
|
+
sourcecode/retrieval/steps_endpoint.py,sha256=yOrTA9mWoIrEBVc_-do8m_AAGqjyFqR7jJ9w5LQXycM,12368
|
|
128
|
+
sourcecode/retrieval/steps_graph.py,sha256=ZWA4i1hwCKiP0AOZ-4PJsLHH84abOYVVh6ERNkdE9v0,10050
|
|
129
|
+
sourcecode/retrieval/steps_impact.py,sha256=M0AwU5Ue7nkj-A7DYgQI2BP0BV1b0TFZRrYIydF-Ajw,11605
|
|
130
|
+
sourcecode/retrieval/steps_intf.py,sha256=Jx5Gnm7UT1jOE7YloD0ee3d8PuliX5FgpdvlHh36OBs,9341
|
|
131
|
+
sourcecode/retrieval/steps_struct.py,sha256=jO9L49hziTlS_xhuhCGUavgyAL3ZAnJSOZB-UA4GaRM,13893
|
|
132
|
+
sourcecode/retrieval/steps_txsec.py,sha256=ltyxFAFLHfUglGLGz7i3tY_bovBoKo1d6R2t1xZTcnk,13608
|
|
115
133
|
sourcecode/telemetry/__init__.py,sha256=6wsJnXsgsL_BtMK4hr5Ae1GToHeWej53F4o_-Tc23MQ,3406
|
|
116
134
|
sourcecode/telemetry/config.py,sha256=u_zctgmA1pVT3Ai5jm-pdLY_5kJTRg4Xq2bvIbGBQE4,3727
|
|
117
135
|
sourcecode/telemetry/consent.py,sha256=LIAO9ohJZF8OuZwM4u1VWtALlYfTCCKq4wV3Vwc7i5Q,2194
|
|
118
136
|
sourcecode/telemetry/events.py,sha256=LtzYfaX9Ilckj5PTvAcTpDa9mLqDsYPDUiDkRa58piY,2580
|
|
119
137
|
sourcecode/telemetry/filters.py,sha256=NHa5T-6DaZduQPFuC34jOqHWQgSizM-Ygq8aZ4j19ng,5834
|
|
120
138
|
sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
|
|
121
|
-
sourcecode-2.
|
|
122
|
-
sourcecode-2.
|
|
123
|
-
sourcecode-2.
|
|
124
|
-
sourcecode-2.
|
|
125
|
-
sourcecode-2.
|
|
139
|
+
sourcecode-2.5.0.dist-info/METADATA,sha256=OGJ148O3ZpmqUj2Ogxv125FILq6ReUC6PmuYyP9t5fs,10851
|
|
140
|
+
sourcecode-2.5.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
141
|
+
sourcecode-2.5.0.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
|
|
142
|
+
sourcecode-2.5.0.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
143
|
+
sourcecode-2.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|