Skip to content

security(job-analysis): bind idempotent replay content to durable command digest #185

Description

@seonghobae

Finding

Canonical #65 revalidated the persisted idempotency row's request digest, snapshot identity, actor, and purpose before replay, then reconstructed the stored snapshot and checked only that snapshot's own content_digest_sha256. It did not prove that the reconstructed replay content still described the command bound to the idempotency key.

A corrupted or inconsistent durable response could therefore return a different but internally self-consistent snapshot under the same analysis_record_id, while job_analysis_write_command.request_digest_sha256 still contained the original request digest. Snapshot-content integrity and command-to-snapshot coherence are separate invariants.

RED → fix

  • RED/test-first successor: 6ae246bcf2ef2d6f312707a070351c0d80ea2f48 (test(job-analysis): bind replayed snapshot to command digest). The regression scripts the exact current command row but reconstructs the same tenant/analysis identity with valid changed analysis_version_code and the corresponding changed snapshot content digest. The predecessor return path would accept and return that internally self-consistent but command-incoherent snapshot.
  • Causal production successor/current head: 462953a7c8b011bcd10293d08e47a5e652da8c0a (fix(job-analysis): verify replay content against command digest). After _load_snapshot(...), replay now recomputes command_digest(...) from the reconstructed snapshot and the already-detached optional Position/Criterion identities and requires equality with the current/recorded request digest before return. Exact same-command replay remains covered.

The production delta is confined to PostgresJobAnalysisPort; no second persistence authority, schema mutation, source copy, mutable downstream dependency, or gate bypass was introduced.

Current acceptance state

Exact-head Job-Analysis API Quality run 33806281982 targets 462953a7c8b011bcd10293d08e47a5e652da8c0a. Jobs 100817419323 (API contract + 100% coverage) and 100817419556 (PostgreSQL integration) are both queued before checkout with steps=[], no assigned runner, selector ubuntu-latest. Hosted GREEN is therefore not claimed.

An exact-head CodeRabbit review was requested for #185 scope; predecessor static evidence is not transferable. #65 remains Draft until terminal exact-head checks and a ruleset-qualifying independent approval exist.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions