Skip to content

dir-core: identity rules, witness evidence, ruler fold (D-IDENTITY-GUID-HOT-0) - #326

Merged
AdaWorldAPI merged 1 commit into
mainfrom
ccr-0455e606-wmtsor
Oct 9, 2026
Merged

AdaWorldAPI merged 1 commit into
mainfrom
ccr-0455e606-wmtsor

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

What

Hybrid identity correspondence across AD, Entra and Exchange Online. Ids are compared as Guid128 numbers, and the three directories are never merged into one node.

  • identity: a declared IdentityRule compiles to a CompiledRule that reads numeric slots only.
    • Encodings: MsGuidBytes16, Base64MsGuidBytes16, Labeled("User_{0}"), GuidText.
    • Decoding is strict: a value is accepted only if it renders back exactly. Absent, malformed and nil stay separate states.
    • Rules: mS-DS-ConsistencyGuid → onPremisesImmutableId, objectGUID → onPremisesImmutableId, backsync → id, and id → ExternalDirectoryObjectId.
    • The objectGUID rule is a separate profile. It is never a fallback for the ConsistencyGuid rule.
  • edge: new EdgeEvidence codes 2–4, one per witness. Code 1 keeps its existing objectGUID meaning.
  • schema: SchemaFamily::ExchangeOnline = 3 (additive). The 512-byte record and the 64-byte edge layouts are unchanged.
  • correspond: three stages.
    • Boundary lanes decode each id once.
    • A sort-merge join fold puts unaligned observations onto the ruler (cold).
    • fold_aligned is the hot path. Slot i is the same user in every column, so each witness is a position-wise compare written into bit planes.
    • Ambiguous or contested counterparts are never placed on the ruler.
  • ogar_az::sync_edges is unchanged; its docs now say it covers the objectGUID profile only.
  • SourceAnchor::from_immutable_id now reuses the dir-core codec. No behaviour change.

The defect

sync_edges compares the decoded immutable id against AD objectGUID. When the source anchor is mS-DS-ConsistencyGuid and it differs from objectGUID, no correspondence is found (F1).

Tests

  • F1–F14 run through the real ogar-ad / ogar-az encoders.
  • A randomized comparison over 3,000 worlds runs against an independent reference that uses plain loops over the fixture spec and never calls the fold. It also checks the ruler fold against the join, slot by slot.
  • That comparison caught two real bugs before this PR:
    • A contested backsync was reported as Confirmed.
    • The ruler placed a counterpart when the forward match was ambiguous.

Sabotage (each mutation applied alone, then reverted)

mutation result caught by
ConsistencyGuid read as objectGUID red F1, F3, F4–F7, F9–F13, randomized
mixed-endian conversion removed red F1, F2, F4–F7, F9–F11, randomized
wrong User_/Group_ label accepted red F8
first match taken on duplicate anchors red F7, randomized
automatic objectGUID fallback red F3, F12, F13, randomized
tenant scope ignored red F11, randomized
contradiction read as non-contradictory red F1, F5, F5b, randomized

Benchmark

cargo run --release -p ogar-dir-core --example identity_fold_bench, run on 1,048,576 slots (16 × 65,536), single thread, Xeon 2.1 GHz:

stage median allocations
ruler fold (3 witnesses, 2 conflict planes, time alignment) 8.2 ms 0
join fold (sort-merge) 200 ms 0
Guid128 equality only 1.2 ms 0
prebuilt HashMap lookup 95 ms 0
index build (cold) 0.4–1.2 s ~95

Not covered

There is no Exchange Online ingest crate. EXO lanes are built from DirRecords of family 3.

🤖 Generated with Claude Code

https://claude.ai/code/session_01G22yT6htkcdyXsihxxXdrg

Hybrid identity correspondence across AD, Entra and Exchange Online,
as numbers, without merging nodes.

- identity: IdentityRule (declaration) + CompiledRule (numeric slots).
  Encodings MsGuidBytes16 / Base64MsGuidBytes16 / Labeled / GuidText,
  strict (renders back or refused), absent / malformed / nil kept apart.
  Rules: ConsistencyGuid -> ImmutableId, objectGUID -> ImmutableId
  (separate profile, no fallback), backsync -> Entra id,
  Entra id -> EXO ExternalDirectoryObjectId.
- edge: EdgeEvidence codes 2-4; code 1 keeps its objectGUID meaning.
- schema: SchemaFamily::ExchangeOnline = 3 (additive).
- correspond: Lanes (boundary decode, once), sort-merge join fold
  (puts unaligned observations onto the ruler, cold), and fold_aligned:
  slot i is the same user in every column, so each witness is a
  position-wise compare into bit planes. Ambiguous or contested
  counterparts never reach the ruler.
- ogar-az sync_edges documented as the objectGUID profile only.
- dir-sim SourceAnchor::from_immutable_id reuses the dir-core codec.

Tests: F1-F14 through the real ogar-ad / ogar-az encoders, plus a
3,000-world randomized comparison with an independent reference that
also checks the ruler fold against the join slot by slot.

Bench (1,048,576 slots, release, one thread, Xeon 2.1 GHz):
ruler fold 8.2 ms median, 0 allocations; join fold 200 ms;
Guid128 equality 1.2 ms; HashMap lookup baseline 95 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G22yT6htkcdyXsihxxXdrg
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 25309cdb-14e8-406b-bc4e-28575a29eb94

📥 Commits

Reviewing files that changed from the base of the PR and between eece7f8 and 0249594.


📒 Files selected for processing (11)
  • crates/ogar-az/src/lib.rs
  • crates/ogar-az/tests/correspond.rs
  • crates/ogar-dir-core/examples/identity_fold_bench.rs
  • crates/ogar-dir-core/src/correspond.rs
  • crates/ogar-dir-core/src/edge.rs
  • crates/ogar-dir-core/src/identity.rs
  • crates/ogar-dir-core/src/label.rs
  • crates/ogar-dir-core/src/lib.rs
  • crates/ogar-dir-core/src/record.rs
  • crates/ogar-dir-core/src/schema.rs
  • crates/ogar-dir-sim/src/identity.rs

 ________________________________________________________________
< 'Works on my machine' is not a QA strategy, it's a confession. >
 ----------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR


  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


Comment @coderabbitai help to get the list of available commands.

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review October 9, 2026 20:42
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T20:43:54.860356Z 0249594 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@AdaWorldAPI
AdaWorldAPI merged commit fd57842 into main Oct 9, 2026
3 of 4 checks passed
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.

2 participants