Release Kerberos v2 - #1
Merged
Merged
Conversation
Added exports for the Constants and Variables modules in index.js to make their contents available to consumers of the package.
Adds logging for denied access attempts when no policy is found for a request in the IsAllowed method. This improves auditability by ensuring all denied requests are logged, not just those with existing policies.
Introduces the KerberosZodSchemas and ZodSchemas classes to allow dynamic construction and injection of Zod schemas for validation. Refactors Kerberos to use these schemas, enabling more flexible and testable validation logic. Updates method signatures and internal logic to support optional schema and Zod instance parameters, and makes isAllowed and checkResources async. This change improves extensibility and decouples schema definitions from the core logic.
Refactored PrincipalMock to use a new PrincipalMockZodSchemas class extending ZodSchemas for schema construction and parsing. Updated constructor and parsing logic to support flexible schema validation. Also updated Kerberos.js to export KerberosZodSchemas.
Replaces direct use of RequestResourceSchema with a ResourceMockZodSchemas class that extends ZodSchemas. Updates ResourceMock to support flexible parsing with schema or zod instance, and encapsulates shape as a private field. This improves schema extensibility and parsing flexibility.
Introduces ZodSchemas-based static parsing and validation methods for Conditions, Constants, DerivedRoles, Variables, KerberosTest, KerberosTests, PrincipalsMock, and ResourcesMock. This change unifies and modernizes schema handling, enabling dynamic Zod schema construction and improved extensibility. Also updates related test and mock classes to use the new parsing approach.
Removed direct zod schema exports and instance schemas from multiple modules, consolidating schema logic into ZodSchemas-based classes. Updated ResourcePolicy to use ResourcePolicyZodSchemas for parsing and validation, and refactored related modules to rely on class-based schema construction. This streamlines schema management and reduces redundant exports.
Removed the 'zod' package from dependencies in package.json and updated the pnpm-lock.yaml to lockfileVersion 9.0. Also set the packageManager field to pnpm@10.10.0 for consistency.
Moved condition strategies to a private field and refactored their implementation to use direct function calls for improved clarity and performance. Simplified condition evaluation by removing the evaluateCondition method and integrating its logic into isFulfilled. Updated schemas to use more concise object definitions for condition strategies.
Introduces a public shape getter to both Conditions and Constants classes for easier access to the parsed shape. Also updates Constants to use a unified parseShape method for consistency.
Replaces schema parsing with a more flexible approach using zod schemas. Adds static parseShape method and updates constructor to handle both schema and zod options. Internal shape is now private and accessed via a getter.
Replaces Object.fromEntries and Object.entries with a for-in loop and hasOwnProperty check for better performance and compatibility.
Simplifies and restructures the role matching process in DerivedRoles.js by removing helper methods and integrating variable and constant population directly into the get() method. Improves clarity and maintainability of role evaluation.
Updated parseConstants, parseVariables, and parseConditions to accept and forward the 'z' option. The constructor now consistently passes 'z' when parsing constants, variables, and conditions, ensuring proper option propagation.
Refactored ResourcePolicy and DerivedRoles to improve parsing of constants, variables, and conditions by passing the zod context. Replaced isAllowed with check in Kerberos for more consistent action/effect evaluation. Updated rule and definition parsing to handle empty arrays and ensure conditions are properly processed with context.
Moved effectAsBoolean logic from Kerberos.js to ResourcePolicy.js, simplifying Kerberos's response parsing and transformation. ResourcePolicy.check now supports effectAsBoolean to return boolean values for effects, improving clarity and maintainability.
Updated Kerberos class methods to consistently pass the 'z' parameter when parsing policies, derived roles, requests, and arguments. Replaced array mapping with for-loops for better readability and control in internal map-building and logging methods. Improved effect handling in logging and resource checking to support boolean results.
Replaced forEach and Object.entries with for-in loops and explicit hasOwnProperty checks in PrincipalsMock, ResourcesMock, and Variables classes. This change ensures only own properties are processed, improving reliability and consistency.
Replaces public properties with private fields in KerberosTest for better encapsulation. Updates constructor and method logic to reference private fields, and improves validation of input parameters in the run method.
Simplifies the construction of PrincipalsMock and ResourcesMock by aggregating mocks into arrays before instantiation. Updates resource and principal lookup logic to use mock class methods directly, improving readability and maintainability.
Replaces public properties with private fields in KerberosTests for better encapsulation. Updates parsing methods to accept an optional 'z' parameter and ensures mocks are constructed with this parameter. Also exports KerberosTestsZodSchemas.
Added 'zod' to package.json for schema validation. Updated KerberosTests and several test files to use zod for stricter schema checks, and improved test coverage for invalid schema scenarios. Refactored ResourcePolicy tests to use the new 'check' method and actions array for effect mapping.
Eliminates Zod-based validation and parsing for checkResources responses in Kerberos.js. The method now directly returns the results array, simplifying the code and removing related schema construction and parsing logic.
Updated Conditions.isFulfilled to handle multiple strategies within a condition object, returning true only if all strategies are fulfilled. Adjusted internal strategy calls and updated related tests to reflect the new logic.
Treat condition objects with no strategy keys as non-matching to avoid vacuous true results (e.g. when a validation backend is absent). Add a unit test asserting an empty strategy object does not match. Also export Metadata schema implementations from src/index.js and add corresponding TypeScript declarations (MetadataZodSchemas, MetadataJsonSchemas, MetadataTypeBoxSchemas) to index.d.ts.
Extract the built-in test harness into a dedicated package subpath to keep dev-only code out of the main entry. Add an exports entry for "./tests" and include tests.js/tests.d.ts in files; tests.js re-exports ./src/Tests. Remove the Tests export from the root src index and delete the Tests namespace from index.d.ts. Update tests and fixtures to import from @alexify/kerberos/tests, and update README and CHANGELOG to document the new subpath and rationale (avoid pulling dev-only code into production bundles).
Update package.json packageManager from pnpm@10.10.0 to pnpm@11.5.0 to standardize the pnpm version used for installs. No other package.json changes included.
Treat the documented base-scope alias '.' as an unset scope in PrincipalPolicy, ResourcePolicy and RolePolicy (return undefined) so Kerberos lookup and metadata normalization are consistent. Refactor KerberosTests to group policies with their tests (#policyGroups) and ensure principals/resources are derived from parsed policies. Improve test utilities and assertions: results are indexed by resource id to validate every expected resource, Zod schema for test actions now accepts Sets or arrays (and normalizes to Set), and several unit tests were added to cover '.' scope behavior, missing-checkResults handling, Zod-enabled construction, and per-policy test isolation.
Add stricter validation for expression descriptors and empty condition arrays. Conditions.js now treats empty any/all/none arrays as non-matching (returns false). caching/codec.js introduces hasExprDescriptorKey, validates that $expr is a string and throws KerberosExprError for non-string values, and updates isExprDescriptor/deepTransform accordingly. index.d.ts adds a Never type. Tests updated/added to cover the new behaviors in Caching.test.js and Conditions.test.js.
Refine Conditions.isFulfilled behavior: use undefined as the default condition, treat non-object/null nested leaves as false (fail-closed), ignore unknown strategy keys for forward compatibility, and ensure empty or unknown-only condition sets evaluate to false to avoid vacuous true results or recursion. Add policyVersion and scope getters to PrincipalMock and ResourceMock, and update TypeScript declarations and tests to cover the new behavior.
Stop using a single shared principals/resources mock across all policies — instead build per-policy PrincipalsMock/ResourcesMock instances and store them with each policy group. Renamed helpers parsePrincipals/parseResources to buildPrincipalsMock/buildResourcesMock and changed them to return the mock instances. Updated KerberosTests constructor and run() to pass the per-policy mocks into tests (removed global shared mocks). Added a unit test that verifies fixture isolation when principal/resource names overlap across policies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Version 2 turns Kerberos.js from a resource-policy engine into a full,
Cerbos-style authorization runtime: three policy types, pluggable validation,
pluggable logging, and cache-agnostic dynamic policies backed by an eval-free,
security-first expression codec. The previously "WIP" features (outputs, scopes,
metadata) are now complete.
Added
Policy types
PrincipalPolicy— Cerbos-style, principal-specific overrides bound to asingle
principaland targetingresource + actiondirectly.RolePolicy— role-centric allowlist policies bound to a singlerole,targeting
resource + allowActions, withparentRolesinheritance (a childrole keeps only actions also allowed by every locally defined parent role).
action is resolved in order:
PrincipalPolicy→RolePolicy→ResourcePolicy→ default
EFFECT_DENY(withEFFECT_DENYwinning ties within the role layer).Authorization features
output.when.ruleActivated/output.when.conditionNotMetexpressions surfaced in
checkResourcesresponses, with asrcthat reflectsthe producing policy (e.g.
resource.expense.vdefault#rule-name).chain (e.g.
acme.corp → acme → '') and scope normalization ('.'≡ base).includeMeta: true; exposesmatchedPolicy,matchedRule,matchedScope, andeffectiveDerivedRoles.C.effectAsBooleanoption forcheckResourcesto returntrue/falseinstead of
EFFECT_ALLOW/EFFECT_DENY.Validation (pluggable backends)
z), JSON Schema + Ajv (ajv), orTypeBox + Ajv (
ajv+typebox).JsonSchemas,TypeBoxSchemas,ZodSchemas,KerberosJsonSchemas,ResourcePolicyJsonSchemas,PrincipalPolicyJsonSchemas,RolePolicyJsonSchemas, …) and helperscreateAjvAdapter/registerAjvKeywords(custom Ajv keywords so function-bearing DSL fields validate at runtime).
Logging (pluggable)
logger: truekeeps the legacyconsoleaudit flow (group + summary + tableconsole-like object behaves the same.evaluated action.
*.start,*.error,*.finishwith timing/duration.fallback results (
isAllowed → false,checkResources → { results: [], … })instead of being thrown.
Caching / storing dynamic policies
CacheLikeintegration: pass any object withget(key)(keyv, cacheable, cache-manager, …); static policies stay in memory and are
always checked first, the cache is only a fallback on a miss.
createSafeExprCodec,serializePolicy,deserializePolicy) built on a user-supplied, pre-configuredjsepinstance.Dynamic policies express
conditions/variables/outputsas{ "$expr": "..." }descriptors evaluated by a strict allowlist interpreter —no
eval/new Function/fn.toString().{ jsep }(built-in evaluator),{ deserialize }(custom), or omitted (cached JSON used as-is).
Auditing & request correlation
kerberosCallIdgenerated per call (Nodecrypto.randomUUID, browsercrypto.randomUUID, or a pseudo UUID v4 fallback) and included in responsesand logs.
getCallIdoption.reqIdpropagated through evaluation, responses, and audit entries.Changed
schemas/folders plus a sharedsrc/schemas/, and validation logic intoper-module
validation/folders plus a sharedsrc/validation/.Constants,Conditions,Outputs,Variables,PrincipalPolicy,RolePolicy, thecaching codec helpers, and all schema/validation builders.
Conditionsnow evaluates multiple strategies (all/any/none) ina single match object via an O(1) strategy dispatch.
kind, principal byid,role by each
principal.roles[]), each combined withpolicyVersion(default
'default') and the scope chain.Performance
types and binary/unary operators (replacing
switchstatements) on the hotexpression-evaluation path; per-
jsepAST cache viaWeakMap.typeofvalidation keyword reduced to an O(1) strategy lookup.checkloops useSet-based role membership lookups and booleaneffect flags instead of
Array.prototype.includesscans; derived-role androle-policy resolution deduplicate via
Set.Security
resolve only against
{ P, R, V, C }plus curated safe builtins (Math,Date,parseInt,parseFloat,Number,String,Boolean,isNaN,isFinite);__proto__/prototype/constructoraccess is blocked at theinterpreter level regardless of how it is written.