Skip to content

Cross-apply conflict-detection atomicity (concurrent /apply TOCTOU) #843

Description

@anatolykoyfman

Follow-up from CodeRabbit review on #842 (deferred there — flagged Major but out of scope for the "surface, never reconcile" series).

Context

ServicePolicyBuilder.build reads the Policy Store (applied_rules_for_scopes), runs detect_conflicts, and raises before compute_and_apply. This is atomic for a single writer: the store read is side-effect-free and the raise precedes any write.

Problem

Two concurrent /apply calls can each read the same clean snapshot, both pass detect_conflicts, then both proceed to the PCE separate read-modify-write and append opposite effects on the same (role.id, scope.id) — neither seeing the other rule. The conflict is silently persisted.

This is a pre-existing property of the PCE read-modify-write, not introduced by #842.

Options

  • Optimistic concurrency: re-read + revalidate conflicts at commit time (CAS on a store version/etag), reject on mismatch.
  • Serialize applies (single-writer lock / queue at the Controller).
  • Transactional store write spanning read → detect → persist.

Acceptance

  • Concurrent opposing applies cannot both commit from the same clean snapshot.
  • Regression test covering two opposing concurrent applies.

Ref: ADR aiac/docs/adr/0001-identify-never-reconcile.md — the "atomic-by-construction" claim is single-writer; this closes the concurrent gap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions