Review safe-polish: docs accuracy, dead imports, no-emoji, geenforce robustness
Some checks failed
CI / backend (push) Has been cancelled
CI / naming (push) Has been cancelled
CI / frontend (push) Has been cancelled

From the full multi-agent review (0 high, 7 medium, 17 low findings). Applies
the mechanical, low-risk items; design/policy findings left for a decision.

Docs accuracy: CLAUDE.md contract 0.10.0 -> 0.11.0 and both stale Alembic head
citations -> 7d24_customfield_searchable / 31 migrations; Dockerfile bundled-
plugin comment fixed (drop nonexistent "equipment", add machines +
measuringtools, count eleven).

Style/naming (LOCKED rules): remove a CSS-escaped pushpin emoji before location
search results (no-emoji policy); rename ManifestEditor shareRoot -> shareroot
(variable mirrors the API field verbatim).

Dead code: remove confirmed-unused imports across ~20 modules (require_role/
require_permission scaffold residue, stray db/Vendor/Model/current_user/Optional/
error_response); drop unused build_scope import + a stale GEENFORCE_API_KEY
docstring clause in geenforce. Migration files left untouched.

Correctness: geenforce ingest robustness - record_enforcement_report now 400s
on a non-dict counts / non-list results instead of 500; _apply_app_link ignores
a non-numeric appid per its docstring instead of 500. Regression tests added.

Backend query.get sweep finished: auth.py refresh -> db.session.get (last one).

910 backend tests pass; pyflakes clean; naming green; frontend build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-07-13 08:02:43 -04:00
parent 85a6ab8645
commit cd353b6432
31 changed files with 263 additions and 234 deletions

View File

@@ -3,11 +3,11 @@
from flask import Blueprint, request
from flask_jwt_extended import jwt_required
from shopdb.api import db, Asset, AssetType, OperatingSystem, Application, AppVersion, AuditLog, Communication, CommunicationType, Setting, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query
from shopdb.api import db, Asset, AssetType, OperatingSystem, Application, AuditLog, Communication, CommunicationType, Setting, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query
from ..models import Computer, ComputerType, ComputerInstalledApp, AccessProtocol, ComputerAccess
from shopdb.api import require_permission, require_role, apply_import_timestamps
from shopdb.api import require_permission, apply_import_timestamps
computers_bp = Blueprint('computers', __name__)

View File

@@ -5,8 +5,7 @@ Two audiences:
Full CRUD + publish lands in P2; this is the P1/first-slice read surface.
- Client (service token, geenforce.fetch scope): GET /manifest serves the
CURRENT PUBLISHED snapshot for a scope, never the live draft. Auth mirrors the
collector's managed-token pattern (X-API-Key or Bearer PAT), plus an optional
GEENFORCE_API_KEY env bootstrap.
collector's managed-token pattern (X-API-Key or Bearer PAT).
"""
from functools import wraps
@@ -219,8 +218,14 @@ def _apply_app_link(entry, payload):
appid = payload.get('appid')
if appid in (None, '', 0):
entry.appid = None
elif db.session.get(Application, int(appid)):
entry.appid = int(appid)
return
# Ignore a non-numeric id rather than 500 (matches the docstring contract).
try:
appid = int(appid)
except (ValueError, TypeError):
return
if db.session.get(Application, appid):
entry.appid = appid
@geenforce_bp.route('/scopes', methods=['POST'])

View File

@@ -147,7 +147,7 @@ class GeEnforcePlugin(BasePlugin):
def import_share_cmd(shareroot, preinstall, scope):
"""Import on-share manifests into draft rows (idempotent rebuild)."""
from flask import current_app
from .importer import discover_share, load_manifest_file, build_scope
from .importer import discover_share, load_manifest_file
from .service import replace_scope_draft
with current_app.app_context():

View File

@@ -127,6 +127,12 @@ def record_enforcement_report(payload):
phase = (payload.get('phase') or 'runtime').strip()
counts = payload.get('counts') or {}
results = payload.get('results') or []
# Guard wrong JSON shapes: a bad type must be a clean 400, not a 500 from a
# later .get()/iteration (the route maps ValueError to 400).
if not isinstance(counts, dict):
raise ValueError('counts must be an object')
if not isinstance(results, list):
raise ValueError('results must be a list')
failed = int(counts.get('failed', 0))
installed = int(counts.get('installed', 0))

View File

@@ -16,7 +16,7 @@ from shopdb.api import (
from ..models import KnowledgeBase
from shopdb.api import require_permission, require_role, apply_import_timestamps
from shopdb.api import require_permission, apply_import_timestamps
knowledgebase_bp = Blueprint('knowledgebase', __name__)

View File

@@ -3,11 +3,11 @@
from flask import Blueprint, request
from flask_jwt_extended import jwt_required
from shopdb.api import db, Asset, AssetType, Vendor, Model, AuditLog, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query, resolve_dualpath_pairs, dualpath_single_machine_enabled
from shopdb.api import db, Asset, AssetType, AuditLog, success_response, error_response, paginated_response, ErrorCodes, get_pagination_params, paginate_query, resolve_dualpath_pairs, dualpath_single_machine_enabled
from ..models import Machine, MachineType
from shopdb.api import require_permission, require_role, apply_import_timestamps
from shopdb.api import require_permission, apply_import_timestamps
machines_bp = Blueprint('machines', __name__)

View File

@@ -7,7 +7,7 @@ from shopdb.api import db, Asset, AssetType, Vendor, AuditLog, success_response,
from ..models import NetworkDevice, NetworkDeviceType, Subnet, VLAN
from shopdb.api import require_permission, require_role, apply_import_timestamps
from shopdb.api import require_permission, apply_import_timestamps
network_bp = Blueprint('network', __name__)

View File

@@ -12,7 +12,7 @@ from shopdb.api import db, success_response, error_response, paginated_response,
from ..models import Notification, NotificationType
from shopdb.api import require_permission, require_role
from shopdb.api import require_permission
notifications_bp = Blueprint('notifications', __name__)

View File

@@ -19,7 +19,7 @@ from ..services import (
logger = logging.getLogger(__name__)
from shopdb.api import require_permission, require_role, apply_import_timestamps
from shopdb.api import require_permission, apply_import_timestamps
printers_asset_bp = Blueprint('printers_asset', __name__)

View File

@@ -8,7 +8,6 @@ from typing import List, Dict, Optional, Type
from flask import Flask, Blueprint
from shopdb.plugins.base import BasePlugin, PluginMeta
from shopdb.api import db
from .models import USBDevice, USBDeviceType, USBCheckout
from .api import usb_bp

View File

@@ -16,7 +16,6 @@ import time
import requests
from flask import current_app
from shopdb.api import db
from shopdb.api import Setting
# Two-level Dell token cache. Dell rate-limits the token endpoint, so a fresh