feat(flow): Prepare event rules for runtime resolution - #4501
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (21)
🚧 Files skipped from review as they are similar to previous changes (20)
Summary by CodeRabbit
WalkthroughThe change adds inventory-backed resource resolution and event enrichment. A new processor validates events and selects effective rules. Resource contracts separate caller hints from canonical data. Rule matching and persisted policy decoding add validation and error classification. ChangesEvent rule processing
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant EventProcessor
participant ResourceResolver
participant InventoryReader
participant EffectiveRuleManager
EventProcessor->>EventProcessor: validate envelope
EventProcessor->>ResourceResolver: resolve and enrich resource
ResourceResolver->>InventoryReader: query by ID or external ID
InventoryReader-->>ResourceResolver: return inventory resource
ResourceResolver-->>EventProcessor: return ResolvedResource
EventProcessor->>EffectiveRuleManager: get effective rule by event type and rack ID
EffectiveRuleManager-->>EventProcessor: return rule or nil
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🔐 TruffleHog Secret Scan✅ No secrets or credentials found! Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉 🕐 Last updated: 2026-08-03 18:38:44 UTC | Commit: d5338db |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (6)
rest-api/flow/internal/eventrule/action_test.go (1)
123-138: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the required table-driven test structure in both changed test segments.
Both segments use direct assertion blocks instead of named
t.Runcases.
rest-api/flow/internal/eventrule/action_test.go#L123-L138: convert theActionCondition.AppliesTocases into named table-driven subtests.rest-api/flow/internal/converter/dao/event_rule_test.go#L39-L55: wrap the invalid-model case in a named table-driven subtest.As per path instructions,
rest-api/**/*_test.gotests must use Testify assertions and named table-drivent.Runsubtests.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/eventrule/action_test.go` around lines 123 - 138, Convert the ActionCondition.AppliesTo assertions in rest-api/flow/internal/eventrule/action_test.go:123-138 into named table-driven t.Run subtests using Testify assertions, preserving all existing cases and outcomes. Also wrap the invalid-model case in rest-api/flow/internal/converter/dao/event_rule_test.go:39-55 in a named table-driven t.Run subtest, with no other behavioral changes.Source: Path instructions
rest-api/flow/internal/inventory/resolver/resolver.go (1)
53-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAttach the resource reference to propagated inventory errors.
ComponentByIDreturns the inventory error without context.ComponentByExternalIDdoes the same at Line 77.rackByIdentifierwraps its inventory error with the reference at Line 160. The result is inconsistent diagnostics: a failed rack lookup reportsrack name "rack-1": ..., while a failed component lookup reports only the transport error.Wrap with
%wto keeperrors.Isclassification intact forclassifyInventoryError.♻️ Proposed fix for consistent error context
resolved, err := r.inventory.GetComponentByID(ctx, id) if err != nil { - return nil, err + return nil, fmt.Errorf("component id %s: %w", id, err) }Apply the same treatment in
ComponentByExternalID:components, err := r.inventory.GetComponentsByExternalIDs( ctx, []string{externalID}, ) if err != nil { return nil, fmt.Errorf("component external id %q: %w", externalID, err) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/inventory/resolver/resolver.go` around lines 53 - 56, Update the error handling in ComponentByID and ComponentByExternalID to wrap inventory errors with the relevant component identifier using fmt.Errorf and %w, matching the contextual pattern used by rackByIdentifier while preserving errors.Is behavior for classifyInventoryError.rest-api/flow/internal/eventrule/processor/processor_test.go (1)
71-92: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a case for terminal envelope rejection.
The three tests cover rule found, rule absent, and rule error. The fourth
preparepath is untested: an invalid envelope must fail withErrTerminal(processor.go Line 48). The PR objectives name terminal input classification as a deliverable, and no test asserts it at theprepareboundary.An envelope with a zero
ID, or with an emptyType, is enough:_, err := newRackProcessor(uuid.New(), nil).prepare( context.Background(), eventrule.Envelope{Type: "test.event"}, ) require.ErrorIs(t, err, ErrTerminal)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/eventrule/processor/processor_test.go` around lines 71 - 92, Add a test alongside TestPrepareReturnsRuleResolutionError that calls prepare with an invalid eventrule.Envelope, such as one with a zero ID or empty Type, and asserts the returned error matches ErrTerminal via require.ErrorIs. Use newRackProcessor with a suitable rack ID and nil resolver to verify terminal input classification at the prepare boundary.rest-api/flow/internal/inventory/resolver/resolver_test.go (2)
124-140: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd cases for the malformed-inventory branches.
The resolver has two terminal branches that no test exercises:
validateComponentrejects a resolved component whoseTypeisdevicetypes.ComponentTypeUnknown(resolver.go Line 178).rackByIdentifierrejects a rack returned asnilor withInfo.ID == uuid.Nil(resolver.go Line 163).Both decide terminal versus retryable classification downstream in
processor/enrichment.go.fakeInventoryalready supports both shapes: pass a component built withdevicetypes.ComponentTypeUnknown, and leavefakeInventory.rackasnil.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/inventory/resolver/resolver_test.go` around lines 124 - 140, Add tests covering malformed inventory in the resolver test cases: use testComponent with devicetypes.ComponentTypeUnknown to exercise validateComponent rejection, and leave fakeInventory.rack nil to exercise rackByIdentifier rejection. Assert each branch produces the expected terminal-versus-retryable classification through the existing enrichment processing path.
90-122: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winOrganize these tests around the production method under test.
Two deviations from the repository test convention:
TestInventoryFailureIsPreservedis named after a behavior, not a production function. It exercisesComponentByIDerror propagation, so it belongs as a named subtest ofTestComponentByID.TestRackByIDAndNamecovers two production methods,RackByIDandRackByName, plus an error case, in one sequential top-level function. Split it intoTestRackByIDandTestRackByName, each with named table-drivent.Runsubtests.The current form also shares mutable
fakeInventorystate across phases: Line 118 setsinventory.errand no phase resets it, so any later assertion added to this function inherits the failure.As per coding guidelines: "Use
testifyassertions and organize tests around the production function or method under test, with one top-levelTest...function and named table-drivent.Runsubtests."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/inventory/resolver/resolver_test.go` around lines 90 - 122, Reorganize the tests by production method: move the inventory error-propagation case into named table-driven subtests under TestComponentByID, split TestRackByIDAndName into separate TestRackByID and TestRackByName functions, and place each success/error scenario in named t.Run subtests. Create fresh fakeInventory instances per subtest so mutable fields such as err do not leak between cases, while preserving the existing assertions.Source: Coding guidelines
rest-api/flow/internal/eventrule/processor/enrichment_test.go (1)
54-89: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtend the table to the remaining terminal branches.
The table proves the terminal-versus-retryable split, which is the important behavior. Three terminal branches added by this PR remain uncovered:
- A component resolved with
RackID == uuid.Nil(enrichment.go Line 84). This branch protects rule scoping, becauseGetEffectivekeys onRackID.- A component whose type fails
ComponentTypeToFlow(enrichment.go Line 91).- An unsupported
resource.KindreachingenrichResource(enrichment.go Line 52).
processorInventoryalready supports the first two: setcomponentsto a component with noRackID, then to one withdevicetypes.ComponentTypeUnknown.Separately, Line 84 compares errors with
==against the table value. A dedicatednotTerminal boolfield states the intent directly and does not depend on sentinel identity.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/eventrule/processor/enrichment_test.go` around lines 54 - 89, Extend TestEnrichClassifiesFailures with terminal cases for a component lacking RackID, an unknown component type causing ComponentTypeToFlow to fail, and an unsupported resource kind reaching enrichResource; configure processorInventory.components accordingly and expect ErrTerminal. Add a notTerminal boolean field to each table entry and use it to assert retryable errors are not terminal instead of comparing wantErr with inventoryErr by identity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rest-api/flow/internal/eventrule/processor/processor.go`:
- Around line 56-63: Add a terminal sentinel for persisted event-rule decode
failures and wrap both policycodec.Unmarshal errors and rule-validation errors
in EventRuleFrom with it. Preserve storage errors from GetEffective unchanged so
callers can retry them, while allowing the sentinel to propagate through
prepare. Update the test to use malformed persisted rule data for the terminal
case; keep errInvalidOverride as an injected storage error.
---
Nitpick comments:
In `@rest-api/flow/internal/eventrule/action_test.go`:
- Around line 123-138: Convert the ActionCondition.AppliesTo assertions in
rest-api/flow/internal/eventrule/action_test.go:123-138 into named table-driven
t.Run subtests using Testify assertions, preserving all existing cases and
outcomes. Also wrap the invalid-model case in
rest-api/flow/internal/converter/dao/event_rule_test.go:39-55 in a named
table-driven t.Run subtest, with no other behavioral changes.
In `@rest-api/flow/internal/eventrule/processor/enrichment_test.go`:
- Around line 54-89: Extend TestEnrichClassifiesFailures with terminal cases for
a component lacking RackID, an unknown component type causing
ComponentTypeToFlow to fail, and an unsupported resource kind reaching
enrichResource; configure processorInventory.components accordingly and expect
ErrTerminal. Add a notTerminal boolean field to each table entry and use it to
assert retryable errors are not terminal instead of comparing wantErr with
inventoryErr by identity.
In `@rest-api/flow/internal/eventrule/processor/processor_test.go`:
- Around line 71-92: Add a test alongside TestPrepareReturnsRuleResolutionError
that calls prepare with an invalid eventrule.Envelope, such as one with a zero
ID or empty Type, and asserts the returned error matches ErrTerminal via
require.ErrorIs. Use newRackProcessor with a suitable rack ID and nil resolver
to verify terminal input classification at the prepare boundary.
In `@rest-api/flow/internal/inventory/resolver/resolver_test.go`:
- Around line 124-140: Add tests covering malformed inventory in the resolver
test cases: use testComponent with devicetypes.ComponentTypeUnknown to exercise
validateComponent rejection, and leave fakeInventory.rack nil to exercise
rackByIdentifier rejection. Assert each branch produces the expected
terminal-versus-retryable classification through the existing enrichment
processing path.
- Around line 90-122: Reorganize the tests by production method: move the
inventory error-propagation case into named table-driven subtests under
TestComponentByID, split TestRackByIDAndName into separate TestRackByID and
TestRackByName functions, and place each success/error scenario in named t.Run
subtests. Create fresh fakeInventory instances per subtest so mutable fields
such as err do not leak between cases, while preserving the existing assertions.
In `@rest-api/flow/internal/inventory/resolver/resolver.go`:
- Around line 53-56: Update the error handling in ComponentByID and
ComponentByExternalID to wrap inventory errors with the relevant component
identifier using fmt.Errorf and %w, matching the contextual pattern used by
rackByIdentifier while preserving errors.Is behavior for classifyInventoryError.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: b0aaa0e5-f1bd-4ae8-a026-c512f2f13d2a
📒 Files selected for processing (18)
rest-api/flow/internal/converter/dao/event_rule_test.gorest-api/flow/internal/eventrule/action.gorest-api/flow/internal/eventrule/action_test.gorest-api/flow/internal/eventrule/doc.gorest-api/flow/internal/eventrule/event.gorest-api/flow/internal/eventrule/manager/manager.gorest-api/flow/internal/eventrule/manager/manager_test.gorest-api/flow/internal/eventrule/policycodec/action_v1.gorest-api/flow/internal/eventrule/policycodec/codec_test.gorest-api/flow/internal/eventrule/processor/enrichment.gorest-api/flow/internal/eventrule/processor/enrichment_test.gorest-api/flow/internal/eventrule/processor/integration_test.gorest-api/flow/internal/eventrule/processor/processor.gorest-api/flow/internal/eventrule/processor/processor_test.gorest-api/flow/internal/inventory/resolver/component_type.gorest-api/flow/internal/inventory/resolver/component_type_test.gorest-api/flow/internal/inventory/resolver/resolver.gorest-api/flow/internal/inventory/resolver/resolver_test.go
d5338db to
a0c239c
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
rest-api/flow/internal/eventrule/processor/processor_test.go (2)
71-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the terminal rule-error classification path.
TestPrepareReturnsRuleResolutionErroronly exercises a plain, unclassified error from the rule resolver. Add a case whereGetEffectivereturns an error wrappingeventrule.ErrInvalidPersistedRule, and assert thatprepareclassifies it viaclassifyRuleErrorasErrTerminal(errors.go lines 26-32). This closes a gap in the "retryable inventory errors" versus terminal rule-decode-error distinction the PR objectives describe.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/eventrule/processor/processor_test.go` around lines 71 - 93, Extend TestPrepareReturnsRuleResolutionError with a resolver error that wraps eventrule.ErrInvalidPersistedRule, then assert prepare returns an error classified as ErrTerminal via classifyRuleError while preserving the existing plain-error assertions.
20-102: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsolidate
preparetests into one table-drivenTestfunction.Four separate top-level Test functions cover
Processor.prepare, and none uset.Runsubtests. Path instructions forrest-api/**/*_test.gorequire one top-levelTest...function organized around the production method, with named table-drivent.Runsubtests. MergeTestPreparePassesEnrichedRackToRuleResolution,TestPrepareTreatsAbsentRuleAsNoop,TestPrepareReturnsRuleResolutionError, andTestPrepareClassifiesInvalidEnvelopeAsTerminalinto a singleTestPreparewith named subtests, following the pattern already used inresolver_test.goand inTestEnrichClassifiesFailuresinenrichment_test.go.♻️ Suggested consolidation sketch
-func TestPreparePassesEnrichedRackToRuleResolution(t *testing.T) { - ... -} - -func TestPrepareTreatsAbsentRuleAsNoop(t *testing.T) { - ... -} - -func TestPrepareReturnsRuleResolutionError(t *testing.T) { - ... -} - -func TestPrepareClassifiesInvalidEnvelopeAsTerminal(t *testing.T) { - ... -} +func TestPrepare(t *testing.T) { + tests := map[string]struct { + // shared fixture fields + }{ + "passes enriched rack to rule resolution": {...}, + "treats absent rule as noop": {...}, + "returns rule resolution error": {...}, + "classifies invalid envelope as terminal": {...}, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + // shared assertion logic + }) + } +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/eventrule/processor/processor_test.go` around lines 20 - 102, Consolidate the four Processor.prepare tests into one top-level TestPrepare function using a table-driven case list and named t.Run subtests. Preserve each existing scenario and assertion—successful enrichment and rule resolution, absent-rule no-op, propagated resolution error, and terminal invalid-envelope classification—following the table-driven patterns in resolver_test.go and TestEnrichClassifiesFailures.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@rest-api/flow/internal/eventrule/processor/processor_test.go`:
- Around line 71-93: Extend TestPrepareReturnsRuleResolutionError with a
resolver error that wraps eventrule.ErrInvalidPersistedRule, then assert prepare
returns an error classified as ErrTerminal via classifyRuleError while
preserving the existing plain-error assertions.
- Around line 20-102: Consolidate the four Processor.prepare tests into one
top-level TestPrepare function using a table-driven case list and named t.Run
subtests. Preserve each existing scenario and assertion—successful enrichment
and rule resolution, absent-rule no-op, propagated resolution error, and
terminal invalid-envelope classification—following the table-driven patterns in
resolver_test.go and TestEnrichClassifiesFailures.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: b71b6128-3e0f-4791-abc0-ab41425d4553
📒 Files selected for processing (21)
rest-api/flow/internal/converter/dao/event_rule.gorest-api/flow/internal/converter/dao/event_rule_test.gorest-api/flow/internal/eventrule/action.gorest-api/flow/internal/eventrule/action_test.gorest-api/flow/internal/eventrule/doc.gorest-api/flow/internal/eventrule/event.gorest-api/flow/internal/eventrule/manager/manager.gorest-api/flow/internal/eventrule/manager/manager_test.gorest-api/flow/internal/eventrule/policycodec/action_v1.gorest-api/flow/internal/eventrule/policycodec/codec_test.gorest-api/flow/internal/eventrule/processor/enrichment.gorest-api/flow/internal/eventrule/processor/enrichment_test.gorest-api/flow/internal/eventrule/processor/errors.gorest-api/flow/internal/eventrule/processor/integration_test.gorest-api/flow/internal/eventrule/processor/processor.gorest-api/flow/internal/eventrule/processor/processor_test.gorest-api/flow/internal/eventrule/store.gorest-api/flow/internal/inventory/resolver/component_type.gorest-api/flow/internal/inventory/resolver/component_type_test.gorest-api/flow/internal/inventory/resolver/resolver.gorest-api/flow/internal/inventory/resolver/resolver_test.go
🚧 Files skipped from review as they are similar to previous changes (13)
- rest-api/flow/internal/eventrule/doc.go
- rest-api/flow/internal/inventory/resolver/component_type_test.go
- rest-api/flow/internal/inventory/resolver/component_type.go
- rest-api/flow/internal/eventrule/policycodec/action_v1.go
- rest-api/flow/internal/eventrule/action.go
- rest-api/flow/internal/eventrule/action_test.go
- rest-api/flow/internal/eventrule/policycodec/codec_test.go
- rest-api/flow/internal/eventrule/processor/integration_test.go
- rest-api/flow/internal/eventrule/manager/manager_test.go
- rest-api/flow/internal/eventrule/processor/processor.go
- rest-api/flow/internal/inventory/resolver/resolver.go
- rest-api/flow/internal/eventrule/event.go
- rest-api/flow/internal/eventrule/manager/manager.go
a0c239c to
e9e201c
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
rest-api/flow/internal/inventory/resolver/resolver_test.go (1)
273-293: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winCapture and assert all inventory lookup arguments.
GetComponentByIDdiscards its UUID.GetComponentsByExternalIDsdiscards its external IDs.GetRackByIdentifierdiscardswithComponents.The tests can pass if the resolver sends an incorrect component identifier or always requests racks without components. Record these arguments in
fakeInventory. Assert them in each successful lookup case. Add at least onewithComponents: truecase.Based on the supplied resolver contracts, identifier and component-loading option propagation are observable resolver behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rest-api/flow/internal/inventory/resolver/resolver_test.go` around lines 273 - 293, The fakeInventory methods GetComponentByID, GetComponentsByExternalIDs, and GetRackByIdentifier must record every lookup argument, including the component UUID, external ID list, and withComponents flag. Update successful resolver lookup tests to assert those captured values, and add coverage for a successful rack lookup with withComponents set to true.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@rest-api/flow/internal/inventory/resolver/resolver_test.go`:
- Around line 273-293: The fakeInventory methods GetComponentByID,
GetComponentsByExternalIDs, and GetRackByIdentifier must record every lookup
argument, including the component UUID, external ID list, and withComponents
flag. Update successful resolver lookup tests to assert those captured values,
and add coverage for a successful rack lookup with withComponents set to true.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 8582794f-c57f-46ec-a5b1-ddb3b2a18434
📒 Files selected for processing (21)
rest-api/flow/internal/converter/dao/event_rule.gorest-api/flow/internal/converter/dao/event_rule_test.gorest-api/flow/internal/eventrule/action.gorest-api/flow/internal/eventrule/action_test.gorest-api/flow/internal/eventrule/doc.gorest-api/flow/internal/eventrule/event.gorest-api/flow/internal/eventrule/manager/manager.gorest-api/flow/internal/eventrule/manager/manager_test.gorest-api/flow/internal/eventrule/policycodec/action_v1.gorest-api/flow/internal/eventrule/policycodec/codec_test.gorest-api/flow/internal/eventrule/processor/enrichment.gorest-api/flow/internal/eventrule/processor/enrichment_test.gorest-api/flow/internal/eventrule/processor/errors.gorest-api/flow/internal/eventrule/processor/integration_test.gorest-api/flow/internal/eventrule/processor/processor.gorest-api/flow/internal/eventrule/processor/processor_test.gorest-api/flow/internal/eventrule/store.gorest-api/flow/internal/inventory/resolver/component_type.gorest-api/flow/internal/inventory/resolver/component_type_test.gorest-api/flow/internal/inventory/resolver/resolver.gorest-api/flow/internal/inventory/resolver/resolver_test.go
🚧 Files skipped from review as they are similar to previous changes (19)
- rest-api/flow/internal/eventrule/policycodec/codec_test.go
- rest-api/flow/internal/eventrule/policycodec/action_v1.go
- rest-api/flow/internal/eventrule/manager/manager.go
- rest-api/flow/internal/converter/dao/event_rule_test.go
- rest-api/flow/internal/converter/dao/event_rule.go
- rest-api/flow/internal/eventrule/doc.go
- rest-api/flow/internal/eventrule/action_test.go
- rest-api/flow/internal/eventrule/store.go
- rest-api/flow/internal/inventory/resolver/component_type.go
- rest-api/flow/internal/eventrule/action.go
- rest-api/flow/internal/eventrule/manager/manager_test.go
- rest-api/flow/internal/eventrule/processor/errors.go
- rest-api/flow/internal/eventrule/processor/enrichment.go
- rest-api/flow/internal/eventrule/event.go
- rest-api/flow/internal/eventrule/processor/processor.go
- rest-api/flow/internal/eventrule/processor/integration_test.go
- rest-api/flow/internal/inventory/resolver/component_type_test.go
- rest-api/flow/internal/eventrule/processor/enrichment_test.go
- rest-api/flow/internal/inventory/resolver/resolver.go
e9e201c to
94248ad
Compare
| } | ||
|
|
||
| reference := fmt.Sprintf("component id %s", id) | ||
| resolved, err := r.inventory.GetComponentByID(ctx, id) |
There was a problem hiding this comment.
NotFound from the inventory store is not mapped to ErrUnresolvable. GetComponentsByExternalIDs returning zero matches is terminal, but GetComponentByID / GetRackByIdentifier NotFound is passed through and classified as retryable by the processor — same "missing resource" outcome, inconsistent retry semantics. Map codes.NotFound (and nil/empty results) to ErrUnresolvable in the resolver, and add a test that exercises a store-style NotFound error rather than only (nil, nil) fakes.
| if err != nil { | ||
| return nil, fmt.Errorf("decode send_alert action spec v1 severity: %w", err) | ||
| } | ||
| if severity.IsUnspecified() { |
There was a problem hiding this comment.
This rejects unspecified severity on decode, but SendAlert.validate still accepts SeverityUnspecified. A rule that passes Create validation can be persisted and then fail every GetEffective with ErrInvalidPersistedRule (terminal). Reject unspecified severity in SendAlert.validate as well so write and read agree.
Leakage detection currently polls NICo Core for leaking information and immediately
submits a force power-off task for each affected component. That is safe as an initial
behavior, but it hard-codes both detection and response in the leak detection job.
We need a pre-defined response at startup, while leaving room for users to define
their own rules later. And the mode should be reusable for other event families such as
thermal alarms, inventory drift, firmware health events, attestation failures, etc.
We plan to create event rules which decide what to do in response to an event.
This PR advances the event-rule work through read-only even processing preparation.
This commit establishes the inventory and processor boundaries needed to turn a
normalized event envelope into an effective rule without executing actions yet.
data, including resolved rack identity and component type
malformed and ambiguous result handling, and retry-safe error preservation
retryable inventory errors, and rack-aware effective rule resolution
the manager boundary
input hints
invalid alert severity
focused tests
Related issues
Type of Change
Breaking Changes
Testing
Additional Notes