Skip to content

feat(apply): add package for applying mapping results to a store - #17

Merged
ewanharris merged 2 commits into
mainfrom
feat/add-apply-package
Oct 8, 2026
Merged

ewanharris merged 2 commits into
mainfrom
feat/add-apply-package

Conversation

@ewanharris

@ewanharris ewanharris commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Description

What problem is being solved?

mapper.Compile + mapper.Evaluate produce a mapper.Result describing the tuple writes and deletes implied by a JSON event, but the library provides no mechanism to apply that result to a store. Callers had to implement the read/diff/write pipeline themselves.

How is it being solved?

A new apply package implements the pipeline behind a narrow TupleClient interface (ReadTuples, WriteTuples). The package has no dependency on the OpenFGA Go SDK; callers supply an adapter.

What changes are made to solve it?

The pipeline runs five phases: validate (structural check before any I/O), read (deduplicated reads per filter), diff (desired vs. existing state per filter), combine (merges direct tuples with filter deltas, deduplicates, and detects conflicts), and write. Two conflict kinds are detected: competing writes on the same URO with different conditions, and a write+delete on the identical tuple. Write-phase errors are wrapped in *WriteError to let callers distinguish retryable failures from hard errors.

References

Review Checklist

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev (apply/README.md)
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

@ewanharris
ewanharris requested a review from a team as a code owner October 6, 2026 19:57
Copilot AI balanced review requested due to automatic review settings October 6, 2026 19:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Desired-state handling and conflict detection can produce incorrect store updates, and duplicate deletes can cause rejected writes.

Review effort: Balanced
Findings: 1 High severity · 2 Medium severity

Open (3)
What changed in this PR

Adds an SDK-independent apply package that reconciles mapper results with a tuple store through a caller-provided adapter.

Changes:

  • Implements validation, reads, diffing, conflict checks, and writes.
  • Distinguishes write-phase failures with WriteError.
  • Adds pipeline documentation and unit tests.
File Description
apply/​README.md Documents pipeline behavior and adapter responsibilities.
apply/​diff.go Computes condition-aware tuple deltas.
apply/​diff_test.go Tests diff behavior and condition changes.
apply/​apply.go Implements reconciliation and error handling.
apply/​apply_test.go Tests pipeline execution and conflicts.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apply/apply.go
Comment thread apply/apply.go
Comment thread apply/apply.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Conflict detection can miss deletions of desired relationships, and validation can accept desired tuples that delete filters ignore.

Review effort: Balanced
Findings: 2 High severity

Open (2)
Resolved since last review (3)

Comment thread apply/apply.go
Comment thread apply/apply.go Outdated
…rage gaps

Two validation gaps in the reconciliation pipeline allowed silent data loss:

1. Overlapping patch operations on the same filter scope could each delete the
   other's already-satisfied desired tuples. Because satisfied desires produce no
   write, they were invisible to the write-vs-delete conflict check in
   combineTuples. Phase 3 now tracks these as satisfiedClaims and combineTuples
   checks them against the full delete set before writing.

2. The per-tuple coverage check in validate accepted a delete filter's scope as
   evidence that a desired tuple was reachable. Delete filters never write tuples;
   coverage now only counts patch filters.

Adds two regression tests, one per fix.

Co-Authored-By: Claude <noreply@anthropic.com>
@ewanharris ewanharris mentioned this pull request Oct 8, 2026
4 tasks done
@ewanharris
ewanharris merged commit 35a804a into main Oct 8, 2026
19 checks passed
@ewanharris
ewanharris deleted the feat/add-apply-package branch October 8, 2026 11:18
@openfga-releaser-bot openfga-releaser-bot Bot mentioned this pull request Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants