Skip to content

Interim hard-reject of accept_data_loss=true rollbacks #104

Closed

Description

@tonibergholm

Question

Ship the interim fail-closed fix for audit finding #2 (critical): reject every Request::Rollback with accept_data_loss = true at the top of crates/agenticd/src/rollback/mod.rs::execute, before any side effects, with a typed error. This is exactly ADR-0014 Decision 4's no-key-configured semantics, shipped ahead of the full gate — the full ADR-0014 implementation ticket supersedes it.

Scope:

  • Gate check first in the handler, before object-store or Postgres work (evidence: crates/agenticd/src/rollback/mod.rs:54, crates/agenticd/src/migrate.rs:106).
  • Regression test: accept_data_loss=true request is rejected with the typed error and causes no side effects.
  • Verify (don't assume) that the broken-prompt demo path never exercises destructive rollback — ADR-0014 Decision 4 asserts it doesn't.

Resolution records: PR link, test names, demo-path verification result.

Activity

  1. added
    ready-for-agentScoped and unambiguous enough for an agent to pick up
    wayfinder:taskWayfinder ticket: work that unblocks a decision or lands a fix
    on Jul 9, 2026
  2. self-assigned this
    on Jul 9, 2026
  3. tonibergholm commented on Jul 9, 2026

    @tonibergholm
    MemberAuthor

    Resolution

    Shipped as PR #114 (pending Toni's review/merge per the map's PR gate).

    What landed: the ADR-0014 Decision 4 fail-closed branch as the entire interim gate — every accept_data_loss=true rollback is rejected at the top of rollback::execute, before any side effects, dry-run included. Typed ApprovalError::KeyNotConfigured, wire-classified as non-retryable Validation with code approval_key_not_configured (a typed downcast arm in wire_error.rs, not a string-sniff; the code is shared with the full gate so alert rules survive the upgrade). Rejections emit the ADR's Decision 5 audit warn line (decision = "rejected_no_key_configured") so probing is operator-visible.

    Tests: rollback_rejects_accept_data_loss_before_side_effects (in-memory end-to-end: typed rejection; schema, memory rows, branch tip untouched; dry-run doesn't bypass) and approval_key_not_configured_classifies_as_non_retryable_validation (wire classification). Full workspace tests, clippy -D warnings, and fmt green.

    Demo-path verification (was an assumption to check): confirmed — run-demo.sh invokes plain agentic rollback baseline --yes, never --accept-data-loss, so no legitimate demo path is blocked. Matches ADR-0014 Decision 4's rationale.

    Facts later tickets depend on: the full gate (#111, now unblocked) turns the unconditional reject into the no-key branch of token verification; migrate::load_steps bypass mechanics are untouched and still covered by the ignored AC3c Postgres test.

  4. added a commit that references this issue on Jul 9, 2026
    aabcbda
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

ready-for-agentScoped and unambiguous enough for an agent to pick upwayfinder:taskWayfinder ticket: work that unblocks a decision or lands a fix

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions