Skip to content

Commit f9e8153

Browse files
author
Agent-Planner
committed
Fix code issues: confidence value handling, duckdns security, and blocked path validation
1 parent 2e86a99 commit f9e8153

6 files changed

Lines changed: 43 additions & 14 deletions

File tree

analyzers/node_analyzer.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def stack_name(self) -> str:
2929
def __init__(self, project_dir: Path):
3030
super().__init__(project_dir)
3131
self._detected_stack = "nodejs" # Default, may change to "express" or "nestjs"
32+
self._detection_confidence: float | None = None # Store confidence from can_analyze()
3233

3334
def can_analyze(self) -> tuple[bool, float]:
3435
"""Detect if this is a Node.js/Express/NestJS project."""
@@ -48,6 +49,7 @@ def can_analyze(self) -> tuple[bool, float]:
4849
if "@nestjs/core" in deps:
4950
self._detected_stack = "nestjs"
5051
confidence = 0.95
52+
self._detection_confidence = confidence
5153
return True, confidence
5254

5355
# Check for Express
@@ -60,24 +62,28 @@ def can_analyze(self) -> tuple[bool, float]:
6062
(self.project_dir / "src" / "routes").exists():
6163
confidence = 0.9
6264

65+
self._detection_confidence = confidence
6366
return True, confidence
6467

6568
# Check for Fastify
6669
if "fastify" in deps:
6770
self._detected_stack = "fastify"
6871
confidence = 0.85
72+
self._detection_confidence = confidence
6973
return True, confidence
7074

7175
# Check for Koa
7276
if "koa" in deps:
7377
self._detected_stack = "koa"
7478
confidence = 0.85
79+
self._detection_confidence = confidence
7580
return True, confidence
7681

7782
# Generic Node.js (has node-specific files but no specific framework)
7883
if "type" in data and data["type"] == "module":
7984
self._detected_stack = "nodejs"
8085
confidence = 0.5
86+
self._detection_confidence = confidence
8187
return True, confidence
8288

8389
except (json.JSONDecodeError, OSError):
@@ -88,7 +94,9 @@ def can_analyze(self) -> tuple[bool, float]:
8894
for file in common_files:
8995
if (self.project_dir / file).exists():
9096
self._detected_stack = "nodejs"
91-
return True, 0.5
97+
confidence = 0.5
98+
self._detection_confidence = confidence
99+
return True, confidence
92100

93101
return False, 0.0
94102

@@ -158,9 +166,13 @@ def analyze(self) -> AnalysisResult:
158166
# Routes is the same as endpoints for Node.js analyzers
159167
routes = endpoints
160168

169+
# Use stored detection confidence with fallback to 0.85, clamped to [0.0, 1.0]
170+
confidence = float(self._detection_confidence) if self._detection_confidence is not None else 0.85
171+
confidence = max(0.0, min(1.0, confidence))
172+
161173
return {
162174
"stack_name": self._detected_stack,
163-
"confidence": 0.85,
175+
"confidence": confidence,
164176
"routes": routes,
165177
"components": components,
166178
"endpoints": endpoints,

analyzers/react_analyzer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ def can_analyze(self) -> tuple[bool, float]:
8585

8686
def analyze(self) -> AnalysisResult:
8787
"""Analyze the React/Next.js project."""
88+
# Keep confidence consistent with detection
89+
_, confidence = self.can_analyze()
90+
8891
routes: list[RouteInfo] = []
8992
components: list[ComponentInfo] = []
9093
endpoints: list[EndpointInfo] = []
@@ -131,7 +134,7 @@ def analyze(self) -> AnalysisResult:
131134

132135
return {
133136
"stack_name": self._detected_stack,
134-
"confidence": 0.9,
137+
"confidence": confidence,
135138
"routes": routes,
136139
"components": components,
137140
"endpoints": endpoints,

api/migrations.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,27 +121,29 @@ def migrate_add_testing_columns(engine) -> None:
121121
last_tested_at DATETIME{optional_col_defs}
122122
)
123123
"""
124-
conn.execute(text(create_sql))
125-
126124
# Step 2: Copy data including optional columns
127125
insert_sql = f"""
128126
INSERT INTO features_new
129127
SELECT id, priority, category, name, description, steps, passes, in_progress,
130128
dependencies, testing_in_progress, last_tested_at{optional_col_names}
131129
FROM features
132130
"""
133-
conn.execute(text(insert_sql))
134131

135-
# Step 3: Atomic table swap - wrap in transaction
136-
# The transaction provides the necessary atomicity
132+
# Wrap entire migration in a single transaction to prevent InvalidRequestError
133+
# from nested conn.begin() calls in SQLAlchemy 2.0
137134
with conn.begin():
138-
# Atomic table swap - rename old, rename new, drop old
135+
# Step 1: Create new table
136+
conn.execute(text(create_sql))
137+
138+
# Step 2: Copy data including optional columns
139+
conn.execute(text(insert_sql))
140+
141+
# Step 3: Atomic table swap - rename old, rename new, drop old
139142
conn.execute(text("ALTER TABLE features RENAME TO features_old"))
140143
conn.execute(text("ALTER TABLE features_new RENAME TO features"))
141144
conn.execute(text("DROP TABLE features_old"))
142145

143-
# Step 4: Recreate indexes
144-
with conn.begin():
146+
# Step 4: Recreate indexes
145147
conn.execute(text("CREATE INDEX IF NOT EXISTS ix_features_id ON features (id)"))
146148
conn.execute(text("CREATE INDEX IF NOT EXISTS ix_features_priority ON features (priority)"))
147149
conn.execute(text("CREATE INDEX IF NOT EXISTS ix_features_passes ON features (passes)"))

scripts/deploy.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,15 @@ ensure_packages() {
114114
configure_duckdns() {
115115
echo "Configuring DuckDNS..."
116116
local cron_file="/etc/cron.d/duckdns"
117+
local token_file="/etc/duckdns_token"
118+
echo "$DUCKDNS_TOKEN" > "$token_file"
119+
chmod 600 "$token_file"
117120
cat > "$cron_file" <<EOF
118-
*/5 * * * * root curl -fsS "https://www.duckdns.org/update?domains=$DUCKDNS_SUBDOMAIN&token=$DUCKDNS_TOKEN&ip=" >/var/log/duckdns.log 2>&1
121+
*/5 * * * * root curl -fsS --get --data-urlencode "domains=$DUCKDNS_SUBDOMAIN" --data-urlencode "token@$token_file" --data-urlencode "ip=" "https://www.duckdns.org/update" >/var/log/duckdns.log 2>&1
119122
EOF
120123
chmod 600 "$cron_file"
121124
# Run once immediately
122-
curl -fsS "https://www.duckdns.org/update?domains=$DUCKDNS_SUBDOMAIN&token=$DUCKDNS_TOKEN&ip=" >/var/log/duckdns.log 2>&1 || true
125+
curl -fsS --get --data-urlencode "domains=$DUCKDNS_SUBDOMAIN" --data-urlencode "token@$token_file" --data-urlencode "ip=" "https://www.duckdns.org/update" >/var/log/duckdns.log 2>&1
123126
}
124127

125128
clone_repo() {

server/routers/cicd.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ async def list_workflows(project_name: str):
203203
return WorkflowListResponse(workflows=[], count=0)
204204

205205
workflows = []
206-
for file in workflows_dir.glob("*.yml"):
206+
for file in workflows_dir.iterdir():
207+
if file.suffix not in (".yml", ".yaml"):
208+
continue
207209
# Determine workflow type from filename
208210
wf_type = "custom"
209211
if file.stem in ["ci", "security", "deploy"]:

server/routers/import_project.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ def validate_path(path: str) -> bool:
6868
Path(r"C:\Program Files").resolve(),
6969
])
7070

71+
# Block Windows user credential/config stores
72+
home = Path.home()
73+
blocked_paths.extend([
74+
(home / "AppData" / "Local").resolve(),
75+
(home / "AppData" / "Roaming").resolve(),
76+
])
77+
7178
# Check if path is a subpath of any blocked location
7279
for blocked in blocked_paths:
7380
try:

0 commit comments

Comments
 (0)