refactor(backend/api): extract TOMService (Step 4 — file 3 of 18)

compliance/api/tom_routes.py (609 LOC) -> 215 LOC thin routes +
434-line TOMService. Request bodies (TOMStateBody, TOMMeasureCreate,
TOMMeasureUpdate, TOMMeasureBulkItem, TOMMeasureBulkBody) moved to
compliance/schemas/tom.py (joining the existing response models from
the Step 3 split).

Single-service split (not two like banner): state, measures CRUD + bulk
upsert, stats, export, and version lookups are all tightly coupled
around the TOMMeasureDB aggregate, so splitting would create artificial
boundaries. TOMService is 434 LOC — comfortably under the 500 hard cap.

Domain error mapping:
  - ConflictError   -> 409 (version conflict on state save; duplicate control_id on create)
  - NotFoundError   -> 404 (missing measure on update; missing version)
  - ValidationError -> 400 (missing tenant_id on DELETE /state)

Legacy test compat: the existing tests/test_tom_routes.py imports
TOMMeasureBulkItem, _parse_dt, _measure_to_dict, and DEFAULT_TENANT_ID
directly from compliance.api.tom_routes. All re-exported via __all__ so
the 44-test file runs unchanged.

mypy.ini flips compliance.api.tom_routes from ignore_errors=True to
False. TOMService carries the scoped Column[T] header.

Verified:
  - 217/217 pytest (173 baseline + 44 TOM) pass
  - OpenAPI 360/484 unchanged
  - mypy compliance/ -> Success on 124 source files
  - tom_routes.py 609 -> 215 LOC
  - Hard-cap violations: 16 -> 15

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-07 19:42:17 +02:00
parent 10073f3ef0
commit d571412657
5 changed files with 675 additions and 502 deletions

View File

@@ -16948,8 +16948,10 @@
"type": "object"
},
"TOMMeasureBulkBody": {
"description": "Request body for POST /tom/measures/bulk.",
"properties": {
"measures": {
"default": [],
"items": {
"$ref": "#/components/schemas/TOMMeasureBulkItem"
},
@@ -16968,13 +16970,11 @@
"title": "Tenant Id"
}
},
"required": [
"measures"
],
"title": "TOMMeasureBulkBody",
"type": "object"
},
"TOMMeasureBulkItem": {
"description": "Single item in a TOMMeasureBulkBody \u2014 no verification fields.",
"properties": {
"applicability": {
"default": "REQUIRED",
@@ -17148,6 +17148,7 @@
"type": "object"
},
"TOMMeasureCreate": {
"description": "Request body for POST /tom/measures.",
"properties": {
"applicability": {
"default": "REQUIRED",
@@ -17354,6 +17355,7 @@
"type": "object"
},
"TOMMeasureUpdate": {
"description": "Request body for PUT /tom/measures/{id} (all fields optional).",
"properties": {
"applicability": {
"anyOf": [
@@ -17583,6 +17585,7 @@
"type": "object"
},
"TOMStateBody": {
"description": "Request body for POST /tom/state (save with optimistic locking).",
"properties": {
"state": {
"additionalProperties": true,
@@ -40733,7 +40736,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response List Measures Api Compliance Tom Measures Get",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -40790,7 +40797,11 @@
"201": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Create Measure Api Compliance Tom Measures Post",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -40831,7 +40842,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Bulk Upsert Measures Api Compliance Tom Measures Bulk Post",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -40884,7 +40899,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Update Measure Api Compliance Tom Measures Measure Id Put",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -40958,7 +40977,9 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"title": "Response List Measure Versions Api Compliance Tom Measures Measure Id Versions Get"
}
}
},
"description": "Successful Response"
@@ -41041,7 +41062,9 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"title": "Response Get Measure Version Api Compliance Tom Measures Measure Id Versions Version Number Get"
}
}
},
"description": "Successful Response"
@@ -41106,7 +41129,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Delete Tom State Api Compliance Tom State Delete",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -41169,7 +41196,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Get Tom State Api Compliance Tom State Get",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -41208,7 +41239,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Save Tom State Api Compliance Tom State Post",
"type": "object"
}
}
},
"description": "Successful Response"
@@ -41257,7 +41292,11 @@
"200": {
"content": {
"application/json": {
"schema": {}
"schema": {
"additionalProperties": true,
"title": "Response Get Tom Stats Api Compliance Tom Stats Get",
"type": "object"
}
}
},
"description": "Successful Response"