Phase 1 Progress Log (Contract Compliance)#
Table of Contents#
- Phase 1 Progress Log (Contract Compliance)
- Table of Contents
- Phase 2 Progress Log (Model/Schema Parity)
- Agent API v1 Contract Violations Audit
- Summary Table
- Endpoint-by-Endpoint Audit
- 1. Agent Endpoints
- 2. Task Endpoints
- 3. Attack Endpoints
- 4. Cracker Endpoints
- 5. General Endpoints
- 6. Model/Schema Mismatches
- 7. Extra/Legacy/Compatibility Endpoints
- 8. Recommendations (Prioritized)
- 9. Deep Model Field-by-Field Audit
- 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#
| File | Endpoint/Area | Violation Type | Description |
|---|---|---|---|
| tasks.py | /client/tasks/{id}/submit_crack | Missing/Incorrect | Endpoint path, implementation, and response do not match contract |
| tasks.py | /client/tasks/* | Parameter Naming | Uses {task_id} instead of {id} in many places |
| tasks.py | /client/tasks/* | Status Codes | Uses 403/409 in places not allowed by contract |
| tasks.py | /client/tasks/* | Error Envelope | Not all errors use { "error": ... } as required |
| agent.py | /client/agents/{id} (GET/PUT) | Path/Param/Status | Uses {agent_id} instead of {id}; status codes may not match contract |
| agent.py | /client/agents/heartbeat | Path/Verb/Contract | POST used, but contract requires POST to /client/agents/{id}/heartbeat |
| agent.py | /client/agents/register | Extra Endpoint | Not present in contract (legacy/compat only) |
| agent.py | /client/agents/state | Extra Endpoint | Not present in contract (legacy/compat only) |
| agent.py | /client/agents/{id}/submit_benchmark | Path/Param/Model | Path param name mismatch; success response now 200 OK with BenchmarkReceipt (resolved); error envelope may not match |
| agent.py | /client/agents/{id}/submit_error | Path/Param/Model | Path and model may not match contract |
| agent.py | /client/agents/{id}/shutdown | Path/Param | Path and param may not match contract |
| attacks.py | /client/attacks/{id} | Param Naming | Uses {attack_id} instead of {id} |
| attacks.py | /client/attacks/{id}/hash_list | Param Naming | Uses {attack_id} instead of {id} |
| crackers.py | /client/crackers/check_for_cracker_update | Query Param | Query param names/types may not match contract |
| general.py | /client/configuration, /client/authenticate | Path/Location | Should be grouped in general.py, but check for param/response compliance |
| v1_http_exception_handler.py | All | Error Envelope | Only 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": ... }
- Path param:
- 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
- Uses
- 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": ... }
- Path param:
- Implementation:
- No such endpoint; instead,
/client/agents/heartbeat(POST, no path param)
- No such endpoint; instead,
- 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 withBenchmarkReceiptJSON body (received_count,processed_count,failed_count,message), 400/401/422 errors as{ "error": ... }
- Path param:
- Implementation:
- Path param is
{agent_id} - Returns
200 OKwithBenchmarkReceiptJSON body on success; contract updated inswagger/v1/swagger.jsonto match - Error envelope may not match
- Path param is
- Violations:
- [MISMATCH] Path param name
- [MISMATCH] Error envelope
- Resolved:
- [OK] Success response: implementation returns
200 OKwithBenchmarkReceiptschema; OpenAPI spec updated to match
- [OK] Success response: implementation returns
/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": ... }
- Path param:
- Implementation:
- Path param is
{agent_id} - Request body model may not match contract (check for required fields, types)
- Error envelope may not match
- Path param is
- 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": ... }
- Path param:
- Implementation:
- Path param is
{agent_id} - Error envelope may not match
- Path param is
- 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": ... }
- GET: returns Task object, 204 if no new task, 401 error as
- 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": ... }
- Path param:
- Implementation:
- Uses
{task_id} - Error envelope may not match
- Uses
- 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": ... }
- Path param:
- Implementation:
- Uses
{task_id} - Error envelope may not match
- 403 used in some cases (not in contract)
- Uses
- 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": ... }
- Path param:
- Implementation:
- Uses
{task_id} - Error envelope may not match
- 403 used in some cases (not in contract)
- Uses
- 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
- Path param:
- Implementation:
- Uses
{task_id} - Error envelope may not match
- 403 used in some cases (not in contract)
- Uses
- 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": ... }
- Path param:
- Implementation:
- Uses
{task_id} - Error envelope may not match
- Uses
- 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": ... }
- Path param:
- Implementation:
- Path is
/tasks/{id}/submit_crack(should be/{id}/submit_crackunder/client/tasks) - Function is a stub (
pass) - Status code and response do not match contract
- Path is
- 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": ... }
- Path param:
- Implementation:
- Uses
{task_id} - Error envelope may not match
- 403/409 used in some cases (not in contract)
- Uses
- 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": ... }
- Path param:
- Implementation:
- Uses
{attack_id} - Error envelope may not match
- Uses
- 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": ... }
- Path param:
- Implementation:
- Uses
{attack_id} - Error envelope may not match
- Uses
- 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": ... }
- Query params:
- 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": ... }
- GET: returns
- 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": ... }
- GET: returns
- 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}/resultare not in the contract- These may cause confusion for v1 clients and should be clearly marked as legacy/compat only
8. Recommendations (Prioritized)#
- Implement all missing endpoints exactly as defined in
contracts/v1_api_swagger.json(highest priority) - Standardize all path parameters to
{id}for v1 endpoints - Align all error responses to use the
{ "error": ... }envelope and only the status codes defined in the contract - Remove or clearly mark any endpoints not present in the v1 contract as legacy/compatibility only
- Audit all response/request models for field parity with the contract, especially for required/nullable fields and enums
- Register the v1 error handler globally to enforce error envelope compliance
- Add strict validation for all query/path/body parameters to match contract types/nullability
- 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#
| Field | Contract Type | Required | Enum/Values | Implementation Type | Required | Enum/Values | Mismatch? | Notes |
|---|---|---|---|---|---|---|---|---|
| id | integer | Yes | int | Yes | ||||
| host_name | string | Yes | str | Yes | ||||
| client_signature | string | Yes | str | Yes | ||||
| state | string | Yes | pending, active, stopped, error | str (AgentState) | Yes | pending, active, stopped, error | ||
| operating_system | string | Yes | linux, windows, macos, other | str (OperatingSystemEnum) | Yes | linux, windows, macos, other | ||
| devices | array[string] | Yes | list[str] | Yes | ||||
| advanced_configuration | object | Yes | AdvancedAgentConfiguration | AdvancedAgentConfiguration | Yes | AdvancedAgentConfiguration |
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 Values | Implementation Values | Mismatch? |
|---|---|---|
| pending, running, paused, completed, failed, abandoned | pending, 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 Values | Implementation Values | Mismatch? |
|---|---|---|
| dictionary, mask, hybrid_dictionary, hybrid_mask | dictionary, mask, hybrid_dictionary, hybrid_mask |
ErrorObject#
| Field | Contract Type | Required | Implementation Type | Required | Mismatch? | Notes |
|---|---|---|---|---|---|---|
| error | string | Yes | str | Yes |
HashcatResult#
| Field | Contract Type | Required | Implementation Type | Required | Mismatch? | Notes |
|---|---|---|---|---|---|---|
| timestamp | string(date-time) | Yes | datetime | Yes | ||
| hash | string | Yes | str | Yes | ||
| plain_text | string | Yes | str | Yes |
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 Values | Implementation Values | Mismatch? |
|---|---|---|
| info, warning, minor, major, critical, fatal | info, warning, minor, major, critical, fatal |
All fields, types, required/optional, and enum values are now exhaustively compared. Any future drift must be re-audited.