Add the PAM access rule evaluation engine and governing-rule resolver#7992
Add the PAM access rule evaluation engine and governing-rule resolver#7992Hinton wants to merge 3 commits into
Conversation
Extract the pure rule-evaluation core from the PAM POC: AccessRuleEngine evaluates a flat list of AccessConditions against request-time AccessSignals, combining results as deny > requires-approval > allow and failing closed on any condition, timezone, or IP it cannot interpret. The engine reads no state and issues no leases. Registered as a singleton (pure and stateless).
Resolve the access rule that governs a cipher for a caller: load the rules on every collection through which the caller reaches the cipher, pick the oldest (earliest creation date, ties broken on id) so selection is deterministic and structural, then evaluate that rule's conditions through the engine to report whether it requires human approval. Malformed stored conditions fail safe to human approval so access never silently auto-approves. Registered scoped; the resolver is the shared entry point the access-request and lease flows build on.
…onverter Close the coverage gaps in the PAM engine slice: - Engine: malformed-but-present CIDR and time-window bounds (fail closed), and matching on a later CIDR/window entry rather than only the first. - Resolver: a governing rule that no longer loads is skipped, both when it is the only candidate (no governance) and when a surviving newer rule takes over; and a time_of_day condition is parsed and evaluated through the resolver. - Port AccessWeekdayJsonConverterTests (source was already on the branch, untested), including the AccessWeekday/DayOfWeek numeric-alignment guard.
🤖 Bitwarden Claude Code ReviewOverall Assessment: APPROVE Reviewed the PAM access-rule evaluation engine ( Code Review DetailsNo blocking findings. Notes considered and intentionally not raised as findings:
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## pam/access-rule-api #7992 +/- ##
======================================================
Coverage ? 62.03%
======================================================
Files ? 2296
Lines ? 100154
Branches ? 9048
======================================================
Hits ? 62130
Misses ? 35838
Partials ? 2186 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
🎟️ Tracking
Part of the PAM POC extraction (peeling
pam/pocinto small, reviewable slices).Important
Stacked on # — base branch is
pam/access-rule-api, notmain. Review/merge this after the base lands. The diff below is only this slice.📔 Objective
Extract the PAM access-rule evaluation engine and the governing-rule resolver from the POC.
AccessRuleEngine(pure, singleton) — evaluates a flat list ofAccessConditions against request-timeAccessSignals, combining results as deny > requires-approval > allow. It reads no state and issues no leases. Every input it cannot interpret (unknown condition kind, unparseable CIDR, unknown/invalid timezone, malformed time-window bounds) fails closed.GoverningRuleResolver(scoped) — resolves the rule governing a cipher for a caller: load the rules on every collection through which the caller reaches the cipher, pick the oldest (earliest creation date, ties broken on id) so selection is deterministic and structural, then evaluate that rule's conditions through the engine to report whether it requires human approval. Malformed stored conditions fail safe to human approval; a rule that no longer loads (deleted after read) stops governing.The resolver is the shared entry point the upcoming access-request and lease slices both build on, which is why it's folded in here rather than split out.
All dependencies (
Collection.AccessRuleId, the collection/collection-cipher repositories, the condition models) already exist on the base branch — this slice adds no persistence, schema, or package changes.⏰ Reminders before review
🦮 Reviewer guidelines
Coverage (49 tests, all green):
time_of_dayparsed/evaluated through the resolver's camelCase deserializer.AccessWeekdayJsonConverter(14): token (de)serialization, case-insensitivity, invalid-token-throws, and theAccessWeekday↔DayOfWeeknumeric-alignment guard the engine's direct cast relies on.