docs(guide): incident.processing-rules — institution match is KEY to KEY (#29) #30

Merged
hiveiq merged 1 commits from docs/29-institution-key-matching into develop 2026-07-17 08:23:51 -04:00
Owner

Refs #29.

What was wrong

incident.processing-rules described institution matching as key → name resolution compared against the ATM's institution name. The code has not worked that way since 2d2dee0 (#290). It compares the rule's institution key directly to atm.institutionKey, case-insensitively:

// #290/#232 — rules are scoped by the tenant KEY, which the UI writes and the ATM now carries.
// This used to resolve the rule's key to a display NAME and compare it to atms.institution —
// NULL for most devices — so NO institution-scoped rule could ever fire.
.filter(r -> r.getInstitution() != null && !r.getInstitution().isBlank()
        && institutionKey != null
        && r.getInstitution().equalsIgnoreCase(institutionKey))

institutionKeyService is still injected on the class but the matcher never calls it.

Why this is worth a PR rather than a note

This documentation actively caused a wrong diagnosis today. Investigating incident#241 — a PBNC EMV fallback rule a customer has now reported twice — the stale gotcha said a key-vs-name mismatch makes a scoped rule "silently fall through to global". I concluded that was happening and that #232 was the root cause, and posted that to a customer-facing ticket.

It was wrong. The rule fires correctly in production:

2026-07-17 05:56:45  SUPPRESS rule 'EMV Fallback Suppression for Peoples Bank ONLY'
                     matched for APPLICATION_ERROR_CARD on ATM NC000936
                     (action=SUPPRESS, institution=PBNC) — skipping incident creation

The retraction is on #241. The Guide is supposed to prevent this class of mistake; here it produced one.

Changes

File Change
claude.md Gotcha rewritten to key-to-key. Adds an explicit "do not re-diagnose a non-firing rule as the #232 bug" note.
internal.md Failure-mode row + the whole "Matching gotcha" section rewritten.
architect.md Evaluation-order step 3 corrected.

Deliberately preserved:

  • The silent fallback to global warning — still true when a rule's key genuinely mismatches. Only the reason changed, and it is still the thing that makes a typo'd key look identical to "no scoped rule exists".
  • claude.md's "rule institution is stored as the KEY, not a display name" — already correct, untouched.
  • The pre-#290 behaviour as historical context, flagged as fixed and live, so the next reader knows it is a closed defect rather than a live trap.

Checks

  • No surviving key → name / findByKey / getInstitutionName claims in the module.
  • Frontmatter intact on all five tabs (Customer/Internal/Architect/Testing/Claude, audiences unchanged).
  • coverage-reconcile.py reports one pre-existing gap (hiveops-feedback → technical.feedback), unrelated to this change and untouched.

🤖 Generated with Claude Code

Refs #29. ## What was wrong `incident.processing-rules` described institution matching as **key → name resolution** compared against the ATM's institution *name*. The code has not worked that way since `2d2dee0` (#290). It compares the rule's `institution` key directly to `atm.institutionKey`, case-insensitively: ```java // #290/#232 — rules are scoped by the tenant KEY, which the UI writes and the ATM now carries. // This used to resolve the rule's key to a display NAME and compare it to atms.institution — // NULL for most devices — so NO institution-scoped rule could ever fire. .filter(r -> r.getInstitution() != null && !r.getInstitution().isBlank() && institutionKey != null && r.getInstitution().equalsIgnoreCase(institutionKey)) ``` `institutionKeyService` is still injected on the class but the matcher never calls it. ## Why this is worth a PR rather than a note This documentation actively caused a wrong diagnosis today. Investigating **incident#241** — a PBNC EMV fallback rule a customer has now reported twice — the stale gotcha said a key-vs-name mismatch makes a scoped rule "silently fall through to global". I concluded that was happening and that #232 was the root cause, and **posted that to a customer-facing ticket**. It was wrong. The rule fires correctly in production: ``` 2026-07-17 05:56:45 SUPPRESS rule 'EMV Fallback Suppression for Peoples Bank ONLY' matched for APPLICATION_ERROR_CARD on ATM NC000936 (action=SUPPRESS, institution=PBNC) — skipping incident creation ``` The retraction is on #241. The Guide is supposed to prevent this class of mistake; here it produced one. ## Changes | File | Change | |---|---| | `claude.md` | Gotcha rewritten to key-to-key. Adds an explicit "do not re-diagnose a non-firing rule as the #232 bug" note. | | `internal.md` | Failure-mode row + the whole "Matching gotcha" section rewritten. | | `architect.md` | Evaluation-order step 3 corrected. | **Deliberately preserved:** - The **silent fallback to global** warning — still true when a rule's key genuinely mismatches. Only the *reason* changed, and it is still the thing that makes a typo'd key look identical to "no scoped rule exists". - `claude.md`'s "rule `institution` is stored as the KEY, not a display name" — already correct, untouched. - The pre-#290 behaviour as **historical context**, flagged as fixed and live, so the next reader knows it is a closed defect rather than a live trap. ## Checks - No surviving `key → name` / `findByKey` / `getInstitutionName` claims in the module. - Frontmatter intact on all five tabs (Customer/Internal/Architect/Testing/Claude, audiences unchanged). - `coverage-reconcile.py` reports one pre-existing gap (`hiveops-feedback → technical.feedback`), unrelated to this change and untouched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hiveiq added 1 commit 2026-07-17 08:21:21 -04:00
The module described pre-#290 behaviour: rule key resolved to a display NAME,
compared to the ATM's institution name. The code has not worked that way since
2d2dee0 — it compares rule.institution to atm.institutionKey directly,
case-insensitively, and never resolves a name. institutionKeyService is still
injected but the matcher does not call it.

This was not harmless. Investigating incident#241 (a PBNC EMV rule a customer
reported twice), the stale gotcha led to the conclusion that the rule was
silently falling through to global and that #232 was the root cause. Both wrong
— the rule fires correctly in prod (Loki: SUPPRESS 'EMV Fallback Suppression
for Peoples Bank ONLY' on NC000936, institution=PBNC). That wrong conclusion was
posted to a customer-facing ticket and had to be retracted. The Guide exists to
prevent exactly that.

- claude.md   — gotcha rewritten to key-to-key; adds a do-not-re-diagnose note
- internal.md — failure-mode row + Matching gotcha section rewritten; keeps the
                silent-fallback-to-global warning, which is still real when a
                key genuinely mismatches, and marks the name-based version as
                historical (#232/#153, fixed 2d2dee0, live 2026-07-16)
- architect.md — evaluation order step 3 corrected

claude.md's "rule institution is stored as the KEY, not a display name" was
already correct and is unchanged.

Refs #29
johannes approved these changes 2026-07-17 08:23:04 -04:00
hiveiq merged commit 9bb8d8b579 into develop 2026-07-17 08:23:51 -04:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: hiveiq-src/hiveops-guide#30