@vess-id/ai-identity 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1533,6 +1533,7 @@ var VPManager = class {
1533
1533
  presentationFrame[key] = true;
1534
1534
  });
1535
1535
  const kbJwtPayload = {
1536
+ iss: options.holderDid,
1536
1537
  aud: options.domain,
1537
1538
  nonce: options.challenge,
1538
1539
  iat: Math.floor(Date.now() / 1e3)
@@ -3907,6 +3908,98 @@ var ConstraintEvaluator = class {
3907
3908
  return {};
3908
3909
  }
3909
3910
  // ============================================================================
3911
+ // PermissionConstraints evaluation (VC-level constraints from PermissionRule)
3912
+ // ============================================================================
3913
+ /**
3914
+ * Evaluate PermissionConstraints from a PermissionRule.
3915
+ *
3916
+ * This is the VC-level constraint evaluator that works with the
3917
+ * normalized PermissionConstraints format (as opposed to GrantConstraints).
3918
+ *
3919
+ * Used by the PolicyEvaluator after rule matching to verify
3920
+ * rule-level constraints are satisfied.
3921
+ */
3922
+ evaluatePermissionConstraints(constraints, context) {
3923
+ const violations = [];
3924
+ const warnings = [];
3925
+ if (constraints.time) {
3926
+ const timeResult = this.checkPermissionTimeConstraint(
3927
+ constraints.time,
3928
+ new Date(context.now * 1e3)
3929
+ );
3930
+ if (timeResult.violation) violations.push(timeResult.violation);
3931
+ if (timeResult.warning) warnings.push(timeResult.warning);
3932
+ }
3933
+ if (constraints.max_invocations !== void 0 && context.invocationCount !== void 0) {
3934
+ const invResult = this.checkInvocationLimit(
3935
+ constraints.max_invocations,
3936
+ context.invocationCount
3937
+ );
3938
+ if (invResult.violation) violations.push(invResult.violation);
3939
+ if (invResult.warning) warnings.push(invResult.warning);
3940
+ }
3941
+ if (constraints.ip_allowlist && constraints.ip_allowlist.length > 0 && context.ipAddress) {
3942
+ const ipResult = this.checkIpAllowlist(constraints.ip_allowlist, context.ipAddress);
3943
+ if (ipResult.violation) violations.push(ipResult.violation);
3944
+ }
3945
+ if (constraints.risk_threshold !== void 0 && context.riskScore !== void 0) {
3946
+ const riskResult = this.checkRiskThreshold(constraints.risk_threshold, context.riskScore);
3947
+ if (riskResult.violation) violations.push(riskResult.violation);
3948
+ if (riskResult.warning) warnings.push(riskResult.warning);
3949
+ }
3950
+ return {
3951
+ allowed: violations.length === 0,
3952
+ violations,
3953
+ warnings
3954
+ };
3955
+ }
3956
+ /**
3957
+ * Check PermissionTimeConstraint (supports both absolute and recurring)
3958
+ */
3959
+ checkPermissionTimeConstraint(time, currentTime) {
3960
+ const nowUnix = Math.floor(currentTime.getTime() / 1e3);
3961
+ if (time.not_before !== void 0 && nowUnix < time.not_before) {
3962
+ return {
3963
+ violation: {
3964
+ type: "time_window",
3965
+ message: `Current time is before not_before (${new Date(time.not_before * 1e3).toISOString()})`,
3966
+ details: { now: nowUnix, not_before: time.not_before }
3967
+ }
3968
+ };
3969
+ }
3970
+ if (time.not_after !== void 0 && nowUnix > time.not_after) {
3971
+ return {
3972
+ violation: {
3973
+ type: "time_window",
3974
+ message: `Current time is after not_after (${new Date(time.not_after * 1e3).toISOString()})`,
3975
+ details: { now: nowUnix, not_after: time.not_after }
3976
+ }
3977
+ };
3978
+ }
3979
+ const timezone = time.timezone || this.options.defaultTimezone;
3980
+ if (time.days_of_week && time.days_of_week.length > 0) {
3981
+ const currentDay = this.getDayOfWeekInTimezone(currentTime, timezone);
3982
+ if (!time.days_of_week.includes(currentDay)) {
3983
+ return {
3984
+ violation: {
3985
+ type: "time_window",
3986
+ message: `Current day (${this.getDayName(currentDay)}) is not in allowed days`,
3987
+ details: { currentDay, allowedDays: time.days_of_week }
3988
+ }
3989
+ };
3990
+ }
3991
+ }
3992
+ if (time.recurring_start && time.recurring_end) {
3993
+ const tw = {
3994
+ start: time.recurring_start,
3995
+ end: time.recurring_end,
3996
+ timezone
3997
+ };
3998
+ return this.checkTimeWindow(tw, currentTime);
3999
+ }
4000
+ return {};
4001
+ }
4002
+ // ============================================================================
3910
4003
  // Helper Methods
3911
4004
  // ============================================================================
3912
4005
  getDayOfWeekInTimezone(date, timezone) {
@@ -3940,21 +4033,38 @@ var ConstraintEvaluator = class {
3940
4033
  const [hours, minutes] = time.split(":").map(Number);
3941
4034
  return hours * 60 + minutes;
3942
4035
  }
4036
+ /**
4037
+ * Check if an IP address is within a CIDR range or matches exactly.
4038
+ * Uses unsigned 32-bit arithmetic to avoid sign-bit issues.
4039
+ * Public for reuse by other services (e.g., LocalPolicyEvaluatorService).
4040
+ */
3943
4041
  isIpInCidr(ip, cidr) {
3944
4042
  try {
4043
+ if (!cidr.includes("/")) {
4044
+ return ip === cidr;
4045
+ }
3945
4046
  const [range, bits] = cidr.split("/");
3946
- const mask = parseInt(bits, 10);
4047
+ const prefix = parseInt(bits, 10);
4048
+ if (isNaN(prefix)) return false;
3947
4049
  const ipNum = this.ipToNumber(ip);
3948
4050
  const rangeNum = this.ipToNumber(range);
3949
- const maskNum = ~(2 ** (32 - mask) - 1);
3950
- return (ipNum & maskNum) === (rangeNum & maskNum);
4051
+ if (ipNum === null || rangeNum === null) return false;
4052
+ const mask = prefix === 0 ? 0 : ~0 << 32 - prefix >>> 0;
4053
+ return (ipNum & mask) === (rangeNum & mask);
3951
4054
  } catch {
3952
4055
  return false;
3953
4056
  }
3954
4057
  }
3955
4058
  ipToNumber(ip) {
3956
- const parts = ip.split(".").map(Number);
3957
- return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3];
4059
+ const parts = ip.split(".");
4060
+ if (parts.length !== 4) return null;
4061
+ let result = 0;
4062
+ for (const part of parts) {
4063
+ const n = parseInt(part, 10);
4064
+ if (isNaN(n) || n < 0 || n > 255) return null;
4065
+ result = result << 8 | n;
4066
+ }
4067
+ return result >>> 0;
3958
4068
  }
3959
4069
  };
3960
4070
  var defaultConstraintEvaluator = new ConstraintEvaluator();