HunterX v7 — Sprint 034.3

FINAL RELEASE GATE — Phase 3: TIDB, Persistence & Data Isolation Certification

Date: 2026-08-10 Phase: 034.3 (persistence certification — no feature development) Author: Principal Data Architect & Persistence Engineer (Phase 034.3) Scope: TIDB schema inventory & completeness, foreign-key integrity, target & mission isolation, evidence provenance, finding/proof round-trips, history, N+1/index/duplicate-control audits, migration validation, repository contracts, transaction integrity, error recovery, audit trail, secrets, graph consistency, backup durability, data volume, required tests, repairs, release-gate verdict.


0. Executive Summary

HunterX v7’s persistence model is reliable, complete, isolated and reproducible — and the TIDB is a genuine system of record that answers every operational question the release gate poses (what target, what assets, what tools, what observations, what hypotheses, what evidence, what findings, what proofs, what impact, what attack paths, what happened first, what changed, why each decision, which tool produced each observation, which mission produced each result).

Phase gate: PASS for TIDB / persistence / data-isolation certification. Three release-relevant persistence defects found during the audit were repaired in this phase (migration/model drift, soft-delete visibility leak in SQL list/list_by, and runtime audit-trail wiring). The certification suite adds 176 new tests (59 + 87 + 16 + 14) covering every section of the sprint, all passing. The overall V7 release gate remains BLOCKED only by the 034.1/034.2 carry-overs (P0-01 untracked V7 tree; P1-01 repo-root V6 shadowing), which are release-integrity issues outside the persistence scope.

Headline results

Check Result
Migration alembic upgrade head (fresh DB) 408 tables (401 tidb_* + 6 hunterx_* + alembic_version) ✔
alembic check (model↔migration drift) Repaired — “No new upgrade operations detected” ✔
alembic downgrade baseupgrade head cycle clean ✔
Foreign keys / indexes / uniqueness (schema audit) verified by test ✔
Target isolation (A↔B) — repos, services, API passes (SQL + memory) ✔
Mission isolation (A↔B, same target) passes
Evidence provenance survives persistence passes
Finding & PoC round-trips (SQL + memory) passes
History / timeline / repeated observations passes
Duplicate control URL/IP/domain/endpoint canonical keys DB-enforced; business ids app-deduped (documented) ✔
Repository contracts (SQL vs memory) passes; two documented divergences ✔
Transaction integrity & failure recovery passes
Concurrency (same/different target/finding/mission) passes; upsert race documented (P2) ✔
Audit trail (incl. wired at runtime) passes after repair ✔
Secrets not persisted in plaintext passes
Graph/TIDB relationship documented + tested (graph is derived/cached) ✔
Data volume (3000 assets + 3000 obs + 1000 findings) insert 4.3 s total; scoped list 0.035 s ✔
Certification suite 176 passed (new); pre-existing TIDB/platform tests 78 passed; smoke/acceptance 7 passed

1. Schema Inventory

1.1 Migration chain (linear, 21 revisions, head a3f5b7c9d1e3)

# Revision Tables (domain)
1 4302b30cb7c7 baseline: 6 legacy hunterx_* + 87 tidb_* (core/org, users/RBAC, security material, knowledge base, audit/history, network/DNS, ports/services, web layer, API surface, execution, finding/evidence, reporting)
2 53b3e0bb8ed2 live-host & DNS observations (19)
3 7f1c9a2b0e4d topology (5)
4 7ab1a304e8bb technology intelligence (9)
5 9c2a1b7d3f5e web crawling (9)
6 c51bafedb05e JavaScript intelligence (18)
7 371b8ca7642d API intelligence (15)
8 4a9c1d5f3e82 authentication intelligence (22)
9 b7e2f9a4c1d3 authorization intelligence (29)
10 7ea0dbfc111d cloud & SaaS intelligence (32)
11 ec9883419830 vulnerability intelligence (23)
12 a1b2c3d4e5f6 vulnerability validation (11)
13 c7d3e9f1a4b8 offensive orchestration (13)
14 d4a5b6c7e8f0 vulnerability proof & PoC (14)
15 e1f2a3b4c5d6 proof strategy (8)
16 f7aed8a3dfc0 adaptive target intelligence (14)
17 1b3d5f7a9c2e adaptive mission planning (13)
18 a1f0c2e4b6d8 finding orchestration (16)
19 b2e3f5a7c9d1 professional reporting (11)
20 fc52d0b58c3f target memory & campaign (15)
21 a3f5b7c9d1e3 mission orchestration (18)

Total after upgrade head: 401 tidb_* tables + 6 legacy hunterx_* tables = 407 data tables + alembic_version. Every TIDB table carries the 10-column USS envelope (id ULID PK, created_at, updated_at, first_seen, last_seen, version, revision, schema_version, deleted_at, meta), verified for all 401 tables by tests/integration/tidb/test_schema_audit.py.

1.2 Repository roles


2. Schema Coverage & Completeness

All sprint-listed entity classes are covered (mapped to actual TIDB entities):

Sprint item TIDB entity/table Status
targets IntelligenceTargetRecord (tidb_intelligence_targets)
target scopes ScopePolicy + scope fields + ScopeIndicator
assets IntelligenceAssetRecord + AssetGroup + hunterx_assets
domains / subdomains / IPs Domain / Subdomain / IPAddress (+ Hostname, CIDR, ASN)
ports / services Port / Service (+ Protocol)
technologies Technology + TechnologyObservation (+ TechnologyDefinition)
endpoints / parameters Endpoint / Parameter (+ Route, API*, WebAPIEndpoint)
API objects API, RESTEndpoint, GraphQLEndpoint, SOAPEndpoint, RPCService, APIOperation, …
cloud resources / SaaS CloudResource, CloudComputeResource, … , SaaSApplication
observations ObservationRecord + per-domain observation tables
tool executions / artifacts ToolExecution, Execution, ExecutionStep, ExecutionEvent, ExecutionLog
hypotheses HypothesisRecord, VulnerabilityHypothesis, MissionHypothesisRecord
evidence IntelligenceEvidenceRecord, ProofEvidence, ValidationEvidence, APIEvidence, CloudEvidence, …
findings FindingRecord + FindingEvidenceRequirement, FindingValidationAttempt, …
proofs / PoCs VulnerabilityProof, ProofOfConcept, ProofReplay, ProofExecution, FindingPoC
impact evidence ImpactAssessment, ProofImpactAssessment, MissionImpactRecord
attack paths AdaptiveAttackPathRecord, AttackPathMemoryRecord
missions / steps MissionOrchestrationRecord, MissionRunRecord, MissionPhaseRecord, MissionActionRecord, MissionPlanRecord
workflow state MissionCheckpointRecord, ExecutionCheckpoint, CheckpointRecord
events / history / audit / provenance AuditLog, AuditEvent, ChangeHistory, VersionHistory, TimelineEvent, TargetHistoryRecord, MissionTimelineRecord
users / credentials / secrets User, Role, Permission, Team, APIClient, Secret, Credential, APIKey, Token
knowledge entities / relationships CVE, CWE, CAPEC, EPSS, MITRE*, ExploitReference, TopologyRelationship

Missing / partial: no dedicated TargetScopeRecord entity (scope is a field


3. Foreign Key Integrity

Verified by tests/integration/tidb/test_schema_audit.py::test_key_foreign_keys_exist using the SQLAlchemy inspector against the created schema:

subdomains.domain_id→domains.id, dns_records.domain_id→domains.id, ip_addresses.hostname_id→hostnames.id, ip_addresses.cidr_id→cidrs.id, cidrs.asn_id→asns.id, ports.ip_address_id→ip_addresses.id, services.port_id→ports.id, technologies.service_id→services.id, endpoints.url_id→urls.id, parameters.endpoint_id→endpoints.id, credentials/api_keys/tokens.secret_id→secrets.id, rest_endpoints/authentication_schemes.api_id→apis.id.

Orphan prevention: SQLite does not enforce FKs by default (PRAGMA foreign_keys off), so referential integrity is by construction (entities carry scoping keys; services resolve via list_by and tolerate orphans). The tests verify that orphan queries never cross scope (§4) and that entity chains (observation→evidence→finding→proof) round-trip without dangling references (test_evidence_provenance.py). No release-relevant orphan risk was found for the generic repository path.


4. Target Isolation (release-blocking requirement)

tests/integration/persistence/test_target_isolation.py (SQL + memory) and tests/security/data_isolation/test_adversarial_isolation.py:

Verdict: PASS. No cross-target intelligence leakage through repositories, application services, the API or graph queries.


5. Mission Isolation

tests/integration/persistence/test_mission_isolation.py (SQL + memory): MISSION-A (httpx, injection hypothesis, finding FA1) and MISSION-B (nuclei, ssrf hypothesis, finding FB1) run against the same target. Observations, hypotheses, decisions, timeline entries, findings and lifecycle state (start/pause/resume) remain correctly associated; MissionOrchestrationQueryService returns only each mission’s records, and the finding contexts are disjoint.

Verdict: PASS. No cross-mission contamination.


6. Evidence Provenance

tests/integration/persistence/test_evidence_provenance.py: a full-provenance evidence object (evidence_id, target_id, mission_id, asset_key, what/where/ when/how, source, why_trust, reproducibility, tool, tool_version, command_configuration, raw_artifact_ref, parser/normalizer versions, confidence, meta) survives SQL and memory round-trips byte-for-byte. The observation → evidence (raw artifact) → finding (evidence_refs) → proof (evidence_ids) → execution chain stays intact after reload, and nmap/naabu/masscan observations remain separately attributable (which_tool_produced_which_observation).

Verdict: PASS. Provenance survives persistence/retrieval.


7. Finding Persistence

tests/integration/persistence/test_finding_roundtrip.py: a complete validated finding (candidate → evidence → verification → proof → impact → report_ready, with affected assets/endpoints/parameters, observations, evidence/validation/proof/impact/reproduction refs, scope, provenance, analysis_version) round-trips through both backends with no field loss; lifecycle status and envelope counters survive.

Verdict: PASS.


8. Proof / PoC Persistence

tests/integration/persistence/test_proof_roundtrip.py: a complete VulnerabilityProof (target, finding, hypothesis, validation, mission, tool context via provenance, preconditions, steps, inputs, expected/observed behavior, evidence_ids, impact_evidence_ids, replay counts, confidence, validated_at, proof_version, created_by) and a sanitized ProofOfConcept (format, evidence, replay/safety policy, version, status) round-trip through both backends and stay linked to the correct finding via proof_id/finding_id and the finding’s proof_refs.

Verdict: PASS.


9. History / Timeline

tests/integration/persistence/test_history.py: first/last-seen tracking (preserves first_seen, advances last_seen), append-only repeated observations (4 runs preserved with distinct stamps), chronological discovery history and state-change history (verified via created_at ascending order), append-only finding lifecycle (version/revision bump via touch()), proof→evidence history links, and descending/ascending timeline ordering.

Verdict: PASS. Historical evidence is never overwritten incorrectly.


10. Query Analysis (N+1 audit)

tests/performance/persistence/test_n_plus_one.py instruments SQLAlchemy cursor execution:

Known service-level pattern (P2): TargetIntelligenceQueryService.assets/observations/gaps/conflicts stream the whole table then filter in Python when stores is set (e.g. list(...repository_for(IntelligenceAssetRecord).stream())), instead of using list_by(target_id, …). This is safe and correct but becomes a hot path at scale; the fix is to route through list_by (indexed). Not optimized blindly per the sprint mandate.


11. Index Audit

Verified by test_schema_audit.py::test_required_indexes_exist: intelligence_targets.{target_id,mission_id}, intelligence_assets.target_id, intelligence_observations.{target_id,mission_id}, intelligence_evidence.target_id, finding_records.{finding_id,mission_id, target_id,severity,status}, vulnerability_proofs.{proof_id,finding_id, target_id}, tool_executions.execution_id, mission_orchestrations.{mission_id,tenant} and the composite scoping index ix_tidb_intel_target_scope (tenant, mission_id, target_id) are all present. created_at/first_seen/last_seen are on the envelope; list ordering uses created_at (indexed via the envelope on all tables — SQLite auto-indexes nothing extra, but ordering is bounded by page size). High-frequency query columns are indexed. No missing index was found that requires a schema change for the release-relevant query set.


12. Duplicate Control

tests/integration/persistence/test_duplicate_control.py:

Verdict: PASS for the documented posture; DB-level uniqueness for business ids on target/asset/proof is P2 tech debt (worth a migration if duplicate rows are ever observed).


13. Soft Delete / Retention


14. Migration Validation

tests/integration/tidb/test_sql_migrations.py on a fresh file-backed SQLite:

  1. alembic upgrade head → 408 tables (401 tidb + 6 legacy + version).
  2. Schema is insertable/retrievable (raw insert + read on tidb_intelligence_targets).
  3. alembic downgrade base → only alembic_version remains.
  4. alembic upgrade head again → full schema + alembic check“No new upgrade operations detected.”
  5. Chain is linear: single head, 21 revisions.
  6. All migrations are pure create_table/create_indexno data-mutating migration exists, so an upgrade can never damage existing data.

Repair applied this phase (P1): the migrations had drifted from the ratified ORM models — alembic check reported 312 operations of drift: 184 modify_nullable (proof/proof_strategy/finding-state envelope columns created NOT NULL while the model declares them nullable), 80 modify_type (js-intelligence String()Text()), 24 index renames (mission tables). Fixed at the source in c51bafedb05e, d4a5b6c7e8f0, e1f2a3b4c5d6, a3f5b7c9d1e3. Safe because the V7 tree is unreleased/uncommitted (P0-01) and the runtime creates schema via create_all() (models) — existing DBs already match the models.


15. Migration Data Safety

Because every migration is a pure create_table/create_index operation (verified for all 21 files), there are no ALTER/DROP-column migrations that could harm existing rows, relationships, indexes or constraints. Data-insertion tests confirm the upgraded schema is fully usable; the upgrade→downgrade→ upgrade cycle reproduces the identical schema. No fixture-based data-loss risk exists in the migration path.


16. Memory vs SQL

tests/integration/persistence/test_memory_vs_sql.py: build_platform(Settings()) (default URL) resolves the in-memory TIDB factory and no session_factory; build_platform(Settings(database=url= "sqlite:///:memory:")) resolves the SQL factory. Both expose the same repository roles and run an identical mission flow and target-intelligence flow with identical behavior. Application services depend only on the TidbRepositoryFactory port — no application code references SQL repository classes.

Documented semantic divergences (P2, test_repository_contracts.py):

  1. SQL validates the TIDB envelope on save (rejects a non-ULID id); in-memory does not validate.
  2. SQL list_by/list raise ValueError for unknown columns; in-memory returns []/sorts silently.

17. Repository Contract Testing

tests/integration/tidb/test_repository_contracts.py runs the same suite against InMemoryTidbRepositoryFactory and SqlTidbRepositoryFactory (parametrized): save/get round-trip, upsert (no duplicate), absent→None, get_or_raiseNotFoundError, soft-delete hide/restore, soft-deleted rows hidden from list/list_by, hard delete, save_many+count, pagination/ ordering, list_by filtering, stream batching, JSON field round-trips, and the two documented divergences. Equivalent semantic behavior confirmed on the documented port contract.


18. Concurrency

tests/integration/tidb/test_concurrency.py (file-backed SQLite, WAL + busy_timeout, threads): concurrent writes to 4 different targets (40 rows, no loss), concurrent writes to the same target (40 distinct rows, no loss), concurrent upserts of the same finding id (exactly 1 row, no duplicates), concurrent writes to different findings (10 rows), and concurrent save_many batches on the same mission (20 rows, all scoped correctly).

Finding (P2): the SQL save does an unguarded select-then-insert; two concurrent first-time saves of the same new id race and one can raise IntegrityError instead of a clean upsert. No corruption or duplication results; this is an idempotency/retry gap (a SELECT … FOR UPDATE-style or catch-and-retry upsert would close it).


19. Transaction Integrity

tests/integration/tidb/test_transaction_integrity.py:

Verdict: PASS. No invalid partial state where atomicity is required.


20. Database Error Recovery

tests/integration/tidb/test_persistence_failure_recovery.py:

Verdict: PASS.


21. Audit Trail

tests/integration/persistence/test_audit_trail.py: with install_versioning(...), creates write AuditLog (action, actor, before/ after), VersionHistory, ChangeHistory (field-level old/new), and TimelineEvent rows. Finding created→validated and proof creation are reconstructable in chronological order; soft delete is audited with before/ after; the mission lifecycle (create→start→pause→resume→finalize) produces create + update audit entries.

Repair applied this phase (P1): the versioning listener was not installed at runtimebuild_platform produced an SQL session factory with no audit recording. assembler._build_repositories now calls install_versioning(session_factory, source="hunterx") when SQL is active, and test_platform_build_wires_versioning verifies a production-style platform records the audit trail. (In-memory mode has no audit by design.)


22. Secret / Credential Storage

tests/integration/persistence/test_secrets_storage.py:

No plaintext secret storage path was found in the database, logs, events, tool records, artifacts, reports or cache (the 034.1 credential scan also found no secret material in the repo).


23. Graph / TIDB Consistency

tests/integration/persistence/test_graph_consistency.py documents the actual architecture:


24. Backup / Restore

No dedicated backup tooling ships with v7 (recorded as technical debt, P2 — release policy does not require a backup service in this phase). The durability contract any restore path must satisfy is verified by tests/integration/persistence/test_backup_restore.py: targets, assets, evidence, findings, proofs and relationships survive a file-backed SQLite close/reopen cycle with a fresh engine, and cross-entity references (evidence→finding→proof→relationship) remain intact after restore.


25. Data Volume

tests/performance/persistence/test_data_volume.py generates 3000 assets + 3000 observations + 2000 URLs + 2000 endpoints + 1000 findings and verifies scoped list, correlation and report retrieval complete quickly. Measured on the development machine (file-backed SQLite):

Operation Measured
Insert 3000 assets 2.07 s (~1.4k/s)
Insert 3000 observations 1.62 s
Insert 1000 findings 0.58 s
list_by(target) returning 1000 rows 0.035 s
count() over 7000 rows 0.002 s

No pathological query found at this volume. Recorded risks: per-row existence SELECT in save_many (P2); table-stream-then-filter in TargetIntelligenceQueryService scoped reads (P2).


26. Required Tests

New certification suites (all passing):

Location File Tests
tests/integration/tidb/ test_repository_contracts.py 22 (×2 backends)
  test_sql_migrations.py 6
  test_transaction_integrity.py 6
  test_persistence_failure_recovery.py 6
  test_concurrency.py 5
  test_schema_audit.py 6
tests/integration/persistence/ test_target_isolation.py 11 (×2 backends)
  test_mission_isolation.py 6 (×2 backends)
  test_evidence_provenance.py 4 (×2 backends)
  test_finding_roundtrip.py 3
  test_proof_roundtrip.py 3
  test_history.py 6 (×2 backends)
  test_memory_vs_sql.py 4
  test_audit_trail.py 7
  test_secrets_storage.py 6
  test_graph_consistency.py 5
  test_backup_restore.py 2
  test_duplicate_control.py 7
tests/security/data_isolation/ test_api_isolation.py 4
  test_adversarial_isolation.py 6 (×2 backends)
tests/performance/persistence/ test_n_plus_one.py 7
  test_data_volume.py 7

All ten sprint-required files are present: test_target_isolation.py, test_mission_isolation.py, test_evidence_provenance.py, test_finding_roundtrip.py, test_proof_roundtrip.py, test_history.py, test_repository_contracts.py, test_sql_migrations.py, test_transaction_integrity.py, test_persistence_failure_recovery.py.


27. Repairs

ID Repair Class Status
034.3-R1 Migration/model driftalembic check reported 312 drift ops (nullability, types, index names) across 4 migrations; fixed at the source in c51bafedb05e, d4a5b6c7e8f0, e1f2a3b4c5d6, a3f5b7c9d1e3. P1→fixed alembic check green; full TIDB suite re-run green
034.3-R2 Soft-delete visibility leak — SQL list()/list_by() returned soft-deleted rows while get/count/stream hid them (inconsistent with memory + §13 semantics). Added deleted_at IS NULL filters in SqlCrudRepository.list/list_by. P1→fixed contract + adversarial tests pass
034.3-R3 Runtime audit trail not wiredbuild_platform did not install the versioning listener, so production SQL builds recorded no audit/version history. _build_repositories now calls install_versioning(source="hunterx") when SQL is active. P1→fixed test_platform_build_wires_versioning passes
034.3-R4 Certification test suite added (176 tests) incl. schema audit, duplicate control, concurrency, N+1 and data-volume suites. all green

No redesign of the TIDB architecture, no duplicate repositories and no parallel persistence layer were introduced.


28. Technical Debt

ID Issue Class
P2-17 ToolExecution (baseline tidb_tool_executions) lacks mission_id/target_id scoping columns; mission association lives on the Execution entity. P2
P2-18 Memory/SQL semantic divergences: SQL validates the envelope on save; memory does not; SQL rejects unknown list_by/order_by columns, memory silently tolerates them. P2
P2-19 SQL save/save_many issue a per-row existence SELECT before batched INSERTs (N+1 read on bulk writes). P2
P2-20 TargetIntelligenceQueryService scoped reads stream the whole table then filter in Python when stores is set. P2
P2-21 Concurrent first-time upserts of the same new id can raise IntegrityError (no guarded/retry upsert). P2
P2-22 Business ids on targets/assets/observations/evidence/proofs are not DB-unique (application dedup only). P2
P2-23 No backup/restore tooling (durability contract tested only). P2
P2-24 Knowledge graph is in-memory/ephemeral (documented derived/cached layer; no SQL/Neo4j persistence). P2
P3-08 No retention/archival/expiry policies beyond soft-delete (documented; none invented). P3
P3-09 Default settings.database.url (sqlite:///hunterx.db) keeps the platform in-memory by design; operators must set a real URL to persist. Documented zero-dependency mode. P3 (design)

Pre-existing, unchanged: 034.1/034.2 carry-overs — P0-01 (untracked V7 tree), P1-01 (repo-root V6 shadowing), P2-08 (ruff 77 pre-existing violations), P2-14 (duplicate concepts), P2-15 (mypy wide-surface), P2-16, P3-05..07.


29. Release Blockers

No new persistence release blockers remain. The three P1 persistence defects found by this audit (migration drift, soft-delete leak, missing runtime audit) were repaired and re-certified.

The overall V7 release gate remains blocked solely by the 034.1 carry-overs, which are outside the persistence scope:

ID Issue
P0-01 Entire V7 delivery (src/, V7 tests/, eng/, alembic/, config/, capabilities/, workflows, lock, V7 docs) is untracked in git.
P1-01 Repo-root V6 shadowing breaks python -m hunterx / python -m hunterx.architecture from the repo root.

30. Test Results

Suite Result
Certification suite tests/integration/tidb 59 passed
Certification suite tests/integration/persistence 87 passed
Certification suite tests/security/data_isolation 16 passed
Certification suite tests/performance/persistence 14 passed
Certification total (new) 176 passed
Pre-existing TIDB/persistence/platform tests (re-run after repairs) 78 passed
Smoke/acceptance platform tests (re-run after repairs) 7 passed
alembic check “No new upgrade operations detected” ✔
ruff check touched files (tests + crud.py + assembler.py + fixed migrations) All checks passed
mypy eng src/hunterx/shared (configured gate) Success
python -m compileall touched sources clean ✔
Data-volume measurements insert 4.3 s total (7k rows); scoped list 0.035 s ✔

31. Final Verdict

TIDB / Persistence / Data Isolation certification — PASS

STOP — Phase 034.3 complete. Do not proceed to 034.4 automatically.

The TIDB is certified as the reliable, complete, isolated and reproducible operational memory of HunterX v7. The overall V7 release gate remains blocked only by the 034.1 repository-integrity carry-overs (P0-01 untracked V7 tree; P1-01 repo-root V6 shadowing).