05/08 Updated code: fixed some issues

This commit is contained in:
Nguyen Ngo
2026-05-08 13:24:07 -04:00
parent 63740656cc
commit 24904c0ec7
3 changed files with 29 additions and 4 deletions
+22 -2
View File
@@ -2,7 +2,7 @@
> **Audience:** AI assistants and developers working on this codebase. > **Audience:** AI assistants and developers working on this codebase.
> **Purpose:** Authoritative reference for architecture, conventions, gotchas, and decisions. > **Purpose:** Authoritative reference for architecture, conventions, gotchas, and decisions.
> **Last reviewed:** May 2026 (Phase B complete — iPad offline inspection app) > **Last reviewed:** May 2026 (Phase B complete — iPad offline inspection app; Critical/Notable hardening pass)
--- ---
@@ -618,7 +618,9 @@ limiter = Limiter(
``` ```
phase1_projects_roles → phase6_features → phase7_mobile_api → phase8_notification_matrix phase1_projects_roles → phase6_features → phase7_mobile_api → phase8_notification_matrix
→ phase9_user_full_name → phase10_customer_password_setup → phase11_director_role → phase9_user_full_name → phase10_customer_password_setup → phase11_director_role
→ phase12_performance_indexes → phase_b_mobile_local_id ← HEAD → phase12_performance_indexes → phase_b_mobile_local_id
→ phase13_issue_facility → phase14_facility_created_at
→ phase15_audit_log_indexes ← HEAD
``` ```
### phase_b_mobile_local_id ### phase_b_mobile_local_id
@@ -626,6 +628,21 @@ phase1_projects_roles → phase6_features → phase7_mobile_api → phase8_notif
Adds `mobile_local_id VARCHAR(64) NULL` + index to both `inspections` and `issues`. Adds `mobile_local_id VARCHAR(64) NULL` + index to both `inspections` and `issues`.
Uses `INFORMATION_SCHEMA.COLUMNS` and `INFORMATION_SCHEMA.STATISTICS` existence checks — safe to re-run. Uses `INFORMATION_SCHEMA.COLUMNS` and `INFORMATION_SCHEMA.STATISTICS` existence checks — safe to re-run.
### phase13_issue_facility
Adds nullable `facility_id` FK column to `issues`; back-fills from `areas.facility_id`; makes `area_id` nullable.
Uses direct `ALTER TABLE` + `INFORMATION_SCHEMA` checks — safe to re-run.
### phase14_facility_created_at
Adds nullable `created_at` `DATETIME` column to `facilities`.
Uses direct `ALTER TABLE` + `INFORMATION_SCHEMA` check — safe to re-run.
### phase15_audit_log_indexes
Adds individual indexes on `audit_logs.action` and `audit_logs.entity_type`.
Uses `INFORMATION_SCHEMA.STATISTICS` existence checks — safe to re-run.
### MySQL ENUM Change Protocol (3 steps — always follow) ### MySQL ENUM Change Protocol (3 steps — always follow)
```sql ```sql
-- 1. Expand -- 1. Expand
@@ -748,6 +765,9 @@ timeout = 30
| 28 | **`hmac.compare_digest()` for token comparison** | Prevents timing oracle attacks | | 28 | **`hmac.compare_digest()` for token comparison** | Prevents timing oracle attacks |
| 29 | **`get_customer_scope()` uses bulk project query** | Replaces per-assignment loop | | 29 | **`get_customer_scope()` uses bulk project query** | Replaces per-assignment loop |
| 30 | **CSV exports always call `log_action(ACTION_EXPORT, ...)`** | Data exports are compliance-relevant audit events | | 30 | **CSV exports always call `log_action(ACTION_EXPORT, ...)`** | Data exports are compliance-relevant audit events |
| 31 | **Do NOT add an explicit `Issue.area` relationship** | `Area.issues` declares `backref='area'`, supplying `Issue.area` automatically. A second declaration on `Issue` raises `ConflictingBackreferences` at startup. The dependency is documented here; do not "fix" it by adding an explicit relationship. |
| 32 | **Do not sync an issue when its parent `LocalInspection.syncStatus == "failed"`** | Submitting without `inspection_id` creates orphaned server records; mark issue `"failed"` instead |
| 33 | **f-string fallback strings must use double-quotes inside single-quoted f-strings** | Python 3.11 raises `SyntaxError` on nested same-delimiter quotes; use `"\u2014"` not `'—'` inside `f'...'` |
--- ---
+3
View File
@@ -70,6 +70,9 @@ class Issue(db.Model):
mobile_local_id = db.Column(db.String(64), nullable=True, index=True) # idempotency key for mobile submissions mobile_local_id = db.Column(db.String(64), nullable=True, index=True) # idempotency key for mobile submissions
# Relationships # Relationships
# NOTE: Issue.area is provided by the backref on Area.issues (facility.py).
# Do NOT add a second explicit db.relationship('Area') here — it conflicts
# with that backref at mapper configuration time (CLAUDE.md rule 31 revised).
facility = db.relationship('Facility', foreign_keys=[facility_id], backref='direct_issues') facility = db.relationship('Facility', foreign_keys=[facility_id], backref='direct_issues')
assigned_user = db.relationship('User', foreign_keys=[assigned_to], backref='assigned_issues') assigned_user = db.relationship('User', foreign_keys=[assigned_to], backref='assigned_issues')
verifier = db.relationship('User', foreign_keys=[verified_by], backref='verified_issues') verifier = db.relationship('User', foreign_keys=[verified_by], backref='verified_issues')
+4 -2
View File
@@ -137,10 +137,12 @@ def send_sla_alerts():
hrs = sla_hours_remaining(issue) hrs = sla_hours_remaining(issue)
deadline = sla_deadline(issue) deadline = sla_deadline(issue)
facility_name = issue.resolved_facility.name if issue.resolved_facility else "\u2014"
if status == 'breached': if status == 'breached':
title = f'🚨 SLA Breached — Issue #{issue.id} ({issue.severity.title()})' title = f'🚨 SLA Breached — Issue #{issue.id} ({issue.severity.title()})'
body = ( body = (
f'Issue #{issue.id} at {issue.resolved_facility.name if issue.resolved_facility else ''} ' f'Issue #{issue.id} at {facility_name} '
f'has breached its SLA deadline. ' f'has breached its SLA deadline. '
f'Severity: {issue.severity.title()}. ' f'Severity: {issue.severity.title()}. '
f'Deadline was {deadline.strftime("%Y-%m-%d %H:%M") if deadline else "N/A"}. ' f'Deadline was {deadline.strftime("%Y-%m-%d %H:%M") if deadline else "N/A"}. '
@@ -149,7 +151,7 @@ def send_sla_alerts():
else: # at_risk else: # at_risk
title = f'⚠️ SLA At Risk — Issue #{issue.id} ({issue.severity.title()})' title = f'⚠️ SLA At Risk — Issue #{issue.id} ({issue.severity.title()})'
body = ( body = (
f'Issue #{issue.id} at {issue.resolved_facility.name if issue.resolved_facility else ''} ' f'Issue #{issue.id} at {facility_name} '
f'is approaching its SLA deadline with approximately ' f'is approaching its SLA deadline with approximately '
f'{abs(hrs):.1f}h remaining. ' f'{abs(hrs):.1f}h remaining. '
f'Severity: {issue.severity.title()}. ' f'Severity: {issue.severity.title()}. '