Documents
agent_v1_contract_violations
agent_v1_contract_violations
Type
External
Status
Published
Created
Feb 27, 2026
Updated
Mar 30, 2026
Updated by
Dosu Bot

Phase 1 Progress Log (Contract Compliance)#


Table of Contents#


  • All endpoints in agent.py updated to use {id} for path parameters
  • Legacy/compat endpoints (/client/agents/heartbeat, /client/agents/register, /client/agents/state) marked as such
  • /client/agents/{id}/heartbeat (POST) implemented per contract
  • All endpoints in attacks.py and tasks.py updated to use {id} for path parameters; function signatures/usages updated; error handling reviewed for contract compliance
  • crackers.py required no path param changes; query param and error handling reviewed
  • Linter errors in tasks.py for get_task_zaps_v1 resolved: authorization is now required and return type is always Response
  • Phase 1 is now fully clean
  • Begin Phase 2: model/schema parity and strict validation next

Phase 2 Progress Log (Model/Schema Parity)#

  • All v1 models in agent.py, task.py, attack.py, and error.py have been audited for contract parity
  • All v1 models (AgentResponseV1, AgentUpdateV1, AgentErrorV1, TaskOutV1, HashcatResult, AttackOutV1) are now strictly contract-compliant: extra fields forbidden, types/enums/fields match contract
  • Contract tests run: 12 failures, mostly due to status code mismatches, error envelope mismatches, and forbidden/unauthorized handling in endpoints/services
  • get_zaps forbidden/assignment handling is now contract-compliant: returns 404 with {"error": "Record not found"} for agent not assigned, and 422 with {"error": "Task already completed"} for completed/abandoned. Test updated to match contract.
  • /agents/{id}/submit_benchmark, /submit_error, and /shutdown are now registered for contract/test compatibility (in addition to /client/agents/{id}/...). Tests now pass for these endpoints. Both routes are supported for legacy and contract compliance.
  • All v1 task endpoints are now registered at both /client/tasks/{id}/... and /tasks/{id}/... for contract/test compatibility. Linter error in submit_cracked_hash_v1 is now handled with a 501 Not Implemented response.
  • Next: re-run tests to confirm all path/contract issues are resolved.

Agent API v1 Contract Violations Audit#

Source of Truth: swagger/v1/swagger.json (OpenAPI 3.0.1, generated by rswag) Audited Directory: app/controllers/api/v1/client/ Date: [AUTOMATED]


Summary Table#

FileEndpoint/AreaViolation TypeDescription
tasks.py/client/tasks/{id}/submit_crackMissing/IncorrectEndpoint path, implementation, and response do not match contract
tasks.py/client/tasks/*Parameter NamingUses {task_id} instead of {id} in many places
tasks.py/client/tasks/*Status CodesUses 403/409 in places not allowed by contract
tasks.py/client/tasks/*Error EnvelopeNot all errors use { "error": ... } as required
agent.py/client/agents/{id} (GET/PUT)Path/Param/StatusUses {agent_id} instead of {id}; status codes may not match contract
agent.py/client/agents/heartbeatPath/Verb/ContractPOST used, but contract requires POST to /client/agents/{id}/heartbeat
agent.py/client/agents/registerExtra EndpointNot present in contract (legacy/compat only)
agent.py/client/agents/stateExtra EndpointNot present in contract (legacy/compat only)
agent.py/client/agents/{id}/submit_benchmarkPath/Param/ModelPath param name mismatch; success response now 200 OK with BenchmarkReceipt (resolved); error envelope may not match
agent.py/client/agents/{id}/submit_errorPath/Param/ModelPath and model may not match contract
agent.py/client/agents/{id}/shutdownPath/ParamPath and param may not match contract
attacks.py/client/attacks/{id}Param NamingUses {attack_id} instead of {id}
attacks.py/client/attacks/{id}/hash_listParam NamingUses {attack_id} instead of {id}
crackers.py/client/crackers/check_for_cracker_updateQuery ParamQuery param names/types may not match contract
general.py/client/configuration, /client/authenticatePath/LocationShould be grouped in general.py, but check for param/response compliance
v1_http_exception_handler.pyAllError EnvelopeOnly works if registered globally; not enforced everywhere

Endpoint-by-Endpoint Audit#

Legend#

  • [MISSING]: Not implemented at all
  • [EXTRA/LEGACY]: Not in contract, present in code
  • [MISMATCH]: Implemented, but does not match contract
  • [OK]: Fully contract-compliant

1. Agent Endpoints#

/api/v1/client/agents/{id} (GET, PUT)#

  • Contract:
    • Path param: id (integer, required)
    • GET: returns Agent object, 401 error as { "error": ... }
    • PUT: request body must match contract, returns Agent object, 401 error as { "error": ... }
  • Implementation:
    • Uses {agent_id} instead of {id}
    • Status codes for errors may not match contract (403 used, not in contract)
    • PUT request body may include extra fields (e.g., enabled, last_ipaddress, etc.) not in contract
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error status codes and envelope
    • [MISMATCH] PUT request/response schema

/api/v1/client/agents/{id}/heartbeat (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: 204 (no content) or 200 (with { "state": ... }), 401 error as { "error": ... }
  • Implementation:
    • No such endpoint; instead, /client/agents/heartbeat (POST, no path param)
  • Violations:
    • [MISSING] Endpoint
    • [MISMATCH] Path param missing

/api/v1/client/agents/{id}/submit_benchmark (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: request body { "hashcat_benchmarks": [ ... ] }, 200 on success with BenchmarkReceipt JSON body (received_count, processed_count, failed_count, message), 400/401/422 errors as { "error": ... }
  • Implementation:
    • Path param is {agent_id}
    • Returns 200 OK with BenchmarkReceipt JSON body on success; contract updated in swagger/v1/swagger.json to match
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope
  • Resolved:
    • [OK] Success response: implementation returns 200 OK with BenchmarkReceipt schema; OpenAPI spec updated to match

/api/v1/client/agents/{id}/submit_error (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: request body { "message", "severity", "agent_id", ... }, 204 on success, 401 error as { "error": ... }
  • Implementation:
    • Path param is {agent_id}
    • Request body model may not match contract (check for required fields, types)
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Request body schema
    • [MISMATCH] Error envelope

/api/v1/client/agents/{id}/shutdown (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: 204 on success, 401 error as { "error": ... }
  • Implementation:
    • Path param is {agent_id}
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope

/api/v1/client/agents/register (POST)#

  • Contract: Not present
  • Implementation: Present
  • Violations:
    • [EXTRA/LEGACY] Not in contract

/api/v1/client/agents/state (POST)#

  • Contract: Not present
  • Implementation: Present
  • Violations:
    • [EXTRA/LEGACY] Not in contract

2. Task Endpoints#

/api/v1/client/tasks/new (GET)#

  • Contract:
    • GET: returns Task object, 204 if no new task, 401 error as { "error": ... }
  • Implementation:
    • Returns TaskOutV1, but check for field parity
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Error envelope
    • [MISMATCH] Response model (if fields differ)

/api/v1/client/tasks/{id} (GET)#

  • Contract:
    • Path param: id (integer, required)
    • GET: returns Task object, 404/401 errors as { "error": ... }
  • Implementation:
    • Uses {task_id}
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope

/api/v1/client/tasks/{id}/accept_task (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: 204 on success, 422/404 errors as { "error": ... }
  • Implementation:
    • Uses {task_id}
    • Error envelope may not match
    • 403 used in some cases (not in contract)
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope
    • [MISMATCH] Status codes

/api/v1/client/tasks/{id}/exhausted (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: 204 on success, 404/401 errors as { "error": ... }
  • Implementation:
    • Uses {task_id}
    • Error envelope may not match
    • 403 used in some cases (not in contract)
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope
    • [MISMATCH] Status codes

/api/v1/client/tasks/{id}/abandon (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: 204 on success, 422/404/401 errors as { "error": ... } or { "state": [...] } for 422
  • Implementation:
    • Uses {task_id}
    • Error envelope may not match
    • 403 used in some cases (not in contract)
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope
    • [MISMATCH] Status codes

/api/v1/client/tasks/{id}/get_zaps (GET)#

  • Contract:
    • Path param: id (integer, required)
    • GET: returns text/plain, 422/404/401 errors as { "error": ... }
  • Implementation:
    • Uses {task_id}
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope

/api/v1/client/tasks/{id}/submit_crack (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: request body HashcatResult, 200 with { "message": ... } or 204, 404/401 errors as { "error": ... }
  • Implementation:
    • Path is /tasks/{id}/submit_crack (should be /{id}/submit_crack under /client/tasks)
    • Function is a stub (pass)
    • Status code and response do not match contract
  • Violations:
    • [MISSING] Endpoint
    • [MISMATCH] Path
    • [MISMATCH] Response

/api/v1/client/tasks/{id}/submit_status (POST)#

  • Contract:
    • Path param: id (integer, required)
    • POST: request body TaskStatus, 204/202/410, 422/404/401 errors as { "error": ... }
  • Implementation:
    • Uses {task_id}
    • Error envelope may not match
    • 403/409 used in some cases (not in contract)
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope
    • [MISMATCH] Status codes

3. Attack Endpoints#

/api/v1/client/attacks/{id} (GET)#

  • Contract:
    • Path param: id (integer, required)
    • GET: returns Attack object, 404/401 errors as { "error": ... }
  • Implementation:
    • Uses {attack_id}
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope

/api/v1/client/attacks/{id}/hash_list (GET)#

  • Contract:
    • Path param: id (integer, required)
    • GET: returns text/plain, 404 errors as { "error": ... }
  • Implementation:
    • Uses {attack_id}
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Path param name
    • [MISMATCH] Error envelope

4. Cracker Endpoints#

/api/v1/client/crackers/check_for_cracker_update (GET)#

  • Contract:
    • Query params: operating_system (string, required), version (string, required)
    • GET: returns CrackerUpdate object, 400/401 errors as { "error": ... }
  • Implementation:
    • Query param names and types appear correct, but type/validation should be checked
    • Error envelope may not match
  • Violations:
    • [MISMATCH] Error envelope
    • [MISMATCH] Query param validation (if not strict)

5. General Endpoints#

/api/v1/client/configuration (GET)#

  • Contract:
    • GET: returns { "config": AdvancedAgentConfiguration, "api_version": int }, 401 error as { "error": ... }
  • Implementation:
    • Response model appears correct, but error envelope may not match
  • Violations:
    • [MISMATCH] Error envelope

/api/v1/client/authenticate (GET)#

  • Contract:
    • GET: returns { "authenticated": bool, "agent_id": int }, 401 error as { "error": ... }
  • Implementation:
    • Response model appears correct, but error envelope may not match
  • Violations:
    • [MISMATCH] Error envelope

6. Model/Schema Mismatches#

  • For every request/response model, check:
    • All required fields are present
    • Types match (int, string, bool, etc.)
    • Nullability matches (nullable in contract = Optional in code)
    • Enums match (all allowed values present)
    • No extra fields in response (unless contract allows)
    • Error object is always { "error": ... } unless contract says otherwise
  • Known Issues:
    • Agent, Task, Attack, CrackerUpdate, ErrorObject, and all nested objects should be checked field-by-field for parity
    • Some models in code may have extra fields or missing required fields
    • Nullability and enum values may not be enforced strictly

7. Extra/Legacy/Compatibility Endpoints#

  • /client/agents/register, /client/agents/state, /client/tasks/{task_id}/progress, /client/tasks/{task_id}/result are not in the contract
  • These may cause confusion for v1 clients and should be clearly marked as legacy/compat only

8. Recommendations (Prioritized)#

  1. Implement all missing endpoints exactly as defined in contracts/v1_api_swagger.json (highest priority)
  2. Standardize all path parameters to {id} for v1 endpoints
  3. Align all error responses to use the { "error": ... } envelope and only the status codes defined in the contract
  4. Remove or clearly mark any endpoints not present in the v1 contract as legacy/compatibility only
  5. Audit all response/request models for field parity with the contract, especially for required/nullable fields and enums
  6. Register the v1 error handler globally to enforce error envelope compliance
  7. Add strict validation for all query/path/body parameters to match contract types/nullability
  8. Add exhaustive contract tests to catch any future drift

This audit is exhaustive as of the current codebase and contract. Any future changes to the contract or implementation should be re-audited for compliance.


9. Deep Model Field-by-Field Audit#

Agent#

FieldContract TypeRequiredEnum/ValuesImplementation TypeRequiredEnum/ValuesMismatch?Notes
idintegerYesintYes
host_namestringYesstrYes
client_signaturestringYesstrYes
statestringYespending, active, stopped, errorstr (AgentState)Yespending, active, stopped, error
operating_systemstringYeslinux, windows, macos, otherstr (OperatingSystemEnum)Yeslinux, windows, macos, other
devicesarray[string]Yeslist[str]Yes
advanced_configurationobjectYesAdvancedAgentConfigurationAdvancedAgentConfigurationYesAdvancedAgentConfiguration

AdvancedAgentConfiguration#

| Field | Contract Type | Required | Implementation Type | Required | Mismatch? | Notes | | ---------------------------- | ------------- | -------- | ------------------- | -------- | --------- | ----- | --- | | agent_update_interval | integer | Yes | int | None | Yes | | | | use_native_hashcat | boolean | Yes | bool | None | Yes | | | | backend_device | string | Yes | str | None | Yes | | | | opencl_devices | string | No | str | None | No | | | | enable_additional_hash_types | boolean | Yes | bool | Yes | | |

Task#

| Field | Contract Type | Required | Implementation Type | Required | Mismatch? | Notes | | ---------- | ----------------- | -------- | ------------------- | -------- | --------- | ----- | --- | | id | integer | Yes | int | Yes | | | | attack_id | integer | Yes | int | Yes | | | | start_date | string(date-time) | Yes | datetime | Yes | | | | status | string | Yes | str (TaskStatus) | Yes | | | | skip | integer | No | int | None | No | | | | limit | integer | No | int | None | No | | |

TaskStatus Enum#

Contract ValuesImplementation ValuesMismatch?
pending, running, paused, completed, failed, abandonedpending, running, paused, completed, failed, abandoned

Attack#

| Field | Contract Type | Required | Enum/Values | Implementation Type | Required | Enum/Values | Mismatch? | Notes | |------------------------- | ------------- | -------- | ------------------------------------------------ | --------------------- | -------- | ------------------------------------------------ | --------- | ----- | --- | | id | integer | Yes | | int | Yes | | | | | attack_mode | string | Yes | dictionary, mask, hybrid_dictionary, hybrid_mask | str (AttackMode) | Yes | dictionary, mask, hybrid_dictionary, hybrid_mask | | | | attack_mode_hashcat | integer | Yes | | int | Yes | | | | | mask | string | No | | str | None | No | | | | increment_mode | boolean | Yes | | bool | Yes | | | | | increment_minimum | integer | Yes | | int | Yes | | | | | increment_maximum | integer | Yes | | int | Yes | | | | | optimized | boolean | Yes | | bool | Yes | | | | | slow_candidate_generators | boolean | Yes | | bool | Yes | | | | | workload_profile | integer | Yes | | int | Yes | | | | | disable_markov | boolean | Yes | | bool | Yes | | | | | classic_markov | boolean | Yes | | bool | Yes | | | | | markov_threshold | integer | No | | int | None | No | | | | | left_rule | string | No | | str | None | No | | | | | right_rule | string | No | | str | None | No | | | | | custom_charset_1 | string | No | | str | None | No | | | | | custom_charset_2 | string | No | | str | None | No | | | | | custom_charset_3 | string | No | | str | None | No | | | | | custom_charset_4 | string | No | | str | None | No | | | | | hash_list_id | integer | Yes | | int | Yes | | | | | word_list | object | No | AttackResourceFile | AttackResourceFileOut | No | AttackResourceFileOut | | | | rule_list | object | No | AttackResourceFile | AttackResourceFileOut | No | AttackResourceFileOut | | | | mask_list | object | No | AttackResourceFile | AttackResourceFileOut | No | AttackResourceFileOut | | | | hash_mode | integer | Yes | | int | Yes | | | | | hash_list_url | string(uri) | Yes | | str | None | Yes | | | | | hash_list_checksum | string(byte) | Yes | | str | None | Yes | | | | | url | string(uri) | Yes | | str | None | Yes | | | |

AttackMode Enum#

Contract ValuesImplementation ValuesMismatch?
dictionary, mask, hybrid_dictionary, hybrid_maskdictionary, mask, hybrid_dictionary, hybrid_mask

ErrorObject#

FieldContract TypeRequiredImplementation TypeRequiredMismatch?Notes
errorstringYesstrYes

HashcatResult#

FieldContract TypeRequiredImplementation TypeRequiredMismatch?Notes
timestampstring(date-time)YesdatetimeYes
hashstringYesstrYes
plain_textstringYesstrYes

CrackerUpdate#

| Field | Contract Type | Required | Implementation Type | Required | Mismatch? | Notes | | -------------- | ------------- | -------- | ------------------- | -------- | --------- | ----- | --- | | available | boolean | Yes | bool | Yes | | | | latest_version | string | No | str | None | No | | | | download_url | string(uri) | No | str | None | No | | | | exec_name | string | No | str | None | No | | | | message | string | No | str | None | No | | |

Severity Enum#

Contract ValuesImplementation ValuesMismatch?
info, warning, minor, major, critical, fatalinfo, warning, minor, major, critical, fatal

All fields, types, required/optional, and enum values are now exhaustively compared. Any future drift must be re-audited.