@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.
@@ -2,7 +2,7 @@
2
2
  * ConstraintEvaluator
3
3
  * Grant制約の評価ロジック
4
4
  */
5
- import { GrantConstraints, TimeWindowConstraint, EvaluationContext, ConstraintEvaluationResult, ConstraintViolation, ConstraintWarning } from '@vess-id/ai-identity-types';
5
+ import { GrantConstraints, TimeWindowConstraint, EvaluationContext, ConstraintEvaluationResult, ConstraintViolation, ConstraintWarning, PermissionConstraints, PermissionTimeConstraint } from '@vess-id/ai-identity-types';
6
6
  export interface ConstraintEvaluatorOptions {
7
7
  /** 警告を発する残り実行回数の閾値 */
8
8
  invocationWarningThreshold?: number;
@@ -54,11 +54,42 @@ export declare class ConstraintEvaluator {
54
54
  violation?: ConstraintViolation;
55
55
  warning?: ConstraintWarning;
56
56
  };
57
+ /**
58
+ * Evaluate PermissionConstraints from a PermissionRule.
59
+ *
60
+ * This is the VC-level constraint evaluator that works with the
61
+ * normalized PermissionConstraints format (as opposed to GrantConstraints).
62
+ *
63
+ * Used by the PolicyEvaluator after rule matching to verify
64
+ * rule-level constraints are satisfied.
65
+ */
66
+ evaluatePermissionConstraints(constraints: PermissionConstraints, context: {
67
+ now: number;
68
+ ipAddress?: string;
69
+ riskScore?: number;
70
+ invocationCount?: number;
71
+ }): {
72
+ allowed: boolean;
73
+ violations: ConstraintViolation[];
74
+ warnings: ConstraintWarning[];
75
+ };
76
+ /**
77
+ * Check PermissionTimeConstraint (supports both absolute and recurring)
78
+ */
79
+ checkPermissionTimeConstraint(time: PermissionTimeConstraint, currentTime: Date): {
80
+ violation?: ConstraintViolation;
81
+ warning?: ConstraintWarning;
82
+ };
57
83
  private getDayOfWeekInTimezone;
58
84
  private getTimeInTimezone;
59
85
  private getDayName;
60
86
  private timeToMinutes;
61
- private isIpInCidr;
87
+ /**
88
+ * Check if an IP address is within a CIDR range or matches exactly.
89
+ * Uses unsigned 32-bit arithmetic to avoid sign-bit issues.
90
+ * Public for reuse by other services (e.g., LocalPolicyEvaluatorService).
91
+ */
92
+ isIpInCidr(ip: string, cidr: string): boolean;
62
93
  private ipToNumber;
63
94
  }
64
95
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"constraint-evaluator.d.ts","sourceRoot":"","sources":["../../src/constraint/constraint-evaluator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,0BAA0B,EAC1B,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,4BAA4B,CAAA;AAEnC,MAAM,WAAW,0BAA0B;IACzC,sBAAsB;IACtB,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kBAAkB;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAQD;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAA4B;gBAE/B,OAAO,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC;IAIzD;;OAEG;IACH,QAAQ,CACN,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,iBAAiB,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,SAAS,CAAC,EAAE,IAAI,GACf,0BAA0B;IAgE7B;;OAEG;IACH,eAAe,CACb,cAAc,CAAC,EAAE,IAAI,EACrB,mBAAmB,CAAC,EAAE,MAAM,GAC3B;QAAE,SAAS,CAAC,EAAE,mBAAmB,CAAA;KAAE;IA4BtC;;OAEG;IACH,oBAAoB,CAClB,cAAc,CAAC,EAAE,MAAM,EACvB,kBAAkB,CAAC,EAAE,MAAM,GAC1B;QAAE,SAAS,CAAC,EAAE,mBAAmB,CAAC;QAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAE;IA8BnE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,oBAAoB,EAChC,WAAW,EAAE,IAAI,GAChB;QAAE,SAAS,CAAC,EAAE,mBAAmB,CAAC;QAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAE;IAoEnE;;OAEG;IACH,gBAAgB,CACd,SAAS,EAAE,MAAM,EAAE,EACnB,SAAS,EAAE,MAAM,GAChB;QAAE,SAAS,CAAC,EAAE,mBAAmB,CAAA;KAAE;IA6BtC;;OAEG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB;QAAE,SAAS,CAAC,EAAE,mBAAmB,CAAC;QAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAE;IA6BnE,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,UAAU;CAInB;AAED;;GAEG;AACH,eAAO,MAAM,0BAA0B,qBAA4B,CAAA;AAEnE;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,iBAAiB,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,SAAS,CAAC,EAAE,IAAI,GACf,0BAA0B,CAE5B"}
1
+ {"version":3,"file":"constraint-evaluator.d.ts","sourceRoot":"","sources":["../../src/constraint/constraint-evaluator.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1605,6 +1605,7 @@ var VPManager = class {
1605
1605
  presentationFrame[key] = true;
1606
1606
  });
1607
1607
  const kbJwtPayload = {
1608
+ iss: options.holderDid,
1608
1609
  aud: options.domain,
1609
1610
  nonce: options.challenge,
1610
1611
  iat: Math.floor(Date.now() / 1e3)
@@ -3976,6 +3977,98 @@ var ConstraintEvaluator = class {
3976
3977
  return {};
3977
3978
  }
3978
3979
  // ============================================================================
3980
+ // PermissionConstraints evaluation (VC-level constraints from PermissionRule)
3981
+ // ============================================================================
3982
+ /**
3983
+ * Evaluate PermissionConstraints from a PermissionRule.
3984
+ *
3985
+ * This is the VC-level constraint evaluator that works with the
3986
+ * normalized PermissionConstraints format (as opposed to GrantConstraints).
3987
+ *
3988
+ * Used by the PolicyEvaluator after rule matching to verify
3989
+ * rule-level constraints are satisfied.
3990
+ */
3991
+ evaluatePermissionConstraints(constraints, context) {
3992
+ const violations = [];
3993
+ const warnings = [];
3994
+ if (constraints.time) {
3995
+ const timeResult = this.checkPermissionTimeConstraint(
3996
+ constraints.time,
3997
+ new Date(context.now * 1e3)
3998
+ );
3999
+ if (timeResult.violation) violations.push(timeResult.violation);
4000
+ if (timeResult.warning) warnings.push(timeResult.warning);
4001
+ }
4002
+ if (constraints.max_invocations !== void 0 && context.invocationCount !== void 0) {
4003
+ const invResult = this.checkInvocationLimit(
4004
+ constraints.max_invocations,
4005
+ context.invocationCount
4006
+ );
4007
+ if (invResult.violation) violations.push(invResult.violation);
4008
+ if (invResult.warning) warnings.push(invResult.warning);
4009
+ }
4010
+ if (constraints.ip_allowlist && constraints.ip_allowlist.length > 0 && context.ipAddress) {
4011
+ const ipResult = this.checkIpAllowlist(constraints.ip_allowlist, context.ipAddress);
4012
+ if (ipResult.violation) violations.push(ipResult.violation);
4013
+ }
4014
+ if (constraints.risk_threshold !== void 0 && context.riskScore !== void 0) {
4015
+ const riskResult = this.checkRiskThreshold(constraints.risk_threshold, context.riskScore);
4016
+ if (riskResult.violation) violations.push(riskResult.violation);
4017
+ if (riskResult.warning) warnings.push(riskResult.warning);
4018
+ }
4019
+ return {
4020
+ allowed: violations.length === 0,
4021
+ violations,
4022
+ warnings
4023
+ };
4024
+ }
4025
+ /**
4026
+ * Check PermissionTimeConstraint (supports both absolute and recurring)
4027
+ */
4028
+ checkPermissionTimeConstraint(time, currentTime) {
4029
+ const nowUnix = Math.floor(currentTime.getTime() / 1e3);
4030
+ if (time.not_before !== void 0 && nowUnix < time.not_before) {
4031
+ return {
4032
+ violation: {
4033
+ type: "time_window",
4034
+ message: `Current time is before not_before (${new Date(time.not_before * 1e3).toISOString()})`,
4035
+ details: { now: nowUnix, not_before: time.not_before }
4036
+ }
4037
+ };
4038
+ }
4039
+ if (time.not_after !== void 0 && nowUnix > time.not_after) {
4040
+ return {
4041
+ violation: {
4042
+ type: "time_window",
4043
+ message: `Current time is after not_after (${new Date(time.not_after * 1e3).toISOString()})`,
4044
+ details: { now: nowUnix, not_after: time.not_after }
4045
+ }
4046
+ };
4047
+ }
4048
+ const timezone = time.timezone || this.options.defaultTimezone;
4049
+ if (time.days_of_week && time.days_of_week.length > 0) {
4050
+ const currentDay = this.getDayOfWeekInTimezone(currentTime, timezone);
4051
+ if (!time.days_of_week.includes(currentDay)) {
4052
+ return {
4053
+ violation: {
4054
+ type: "time_window",
4055
+ message: `Current day (${this.getDayName(currentDay)}) is not in allowed days`,
4056
+ details: { currentDay, allowedDays: time.days_of_week }
4057
+ }
4058
+ };
4059
+ }
4060
+ }
4061
+ if (time.recurring_start && time.recurring_end) {
4062
+ const tw = {
4063
+ start: time.recurring_start,
4064
+ end: time.recurring_end,
4065
+ timezone
4066
+ };
4067
+ return this.checkTimeWindow(tw, currentTime);
4068
+ }
4069
+ return {};
4070
+ }
4071
+ // ============================================================================
3979
4072
  // Helper Methods
3980
4073
  // ============================================================================
3981
4074
  getDayOfWeekInTimezone(date, timezone) {
@@ -4009,21 +4102,38 @@ var ConstraintEvaluator = class {
4009
4102
  const [hours, minutes] = time.split(":").map(Number);
4010
4103
  return hours * 60 + minutes;
4011
4104
  }
4105
+ /**
4106
+ * Check if an IP address is within a CIDR range or matches exactly.
4107
+ * Uses unsigned 32-bit arithmetic to avoid sign-bit issues.
4108
+ * Public for reuse by other services (e.g., LocalPolicyEvaluatorService).
4109
+ */
4012
4110
  isIpInCidr(ip, cidr) {
4013
4111
  try {
4112
+ if (!cidr.includes("/")) {
4113
+ return ip === cidr;
4114
+ }
4014
4115
  const [range, bits] = cidr.split("/");
4015
- const mask = parseInt(bits, 10);
4116
+ const prefix = parseInt(bits, 10);
4117
+ if (isNaN(prefix)) return false;
4016
4118
  const ipNum = this.ipToNumber(ip);
4017
4119
  const rangeNum = this.ipToNumber(range);
4018
- const maskNum = ~(2 ** (32 - mask) - 1);
4019
- return (ipNum & maskNum) === (rangeNum & maskNum);
4120
+ if (ipNum === null || rangeNum === null) return false;
4121
+ const mask = prefix === 0 ? 0 : ~0 << 32 - prefix >>> 0;
4122
+ return (ipNum & mask) === (rangeNum & mask);
4020
4123
  } catch {
4021
4124
  return false;
4022
4125
  }
4023
4126
  }
4024
4127
  ipToNumber(ip) {
4025
- const parts = ip.split(".").map(Number);
4026
- return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3];
4128
+ const parts = ip.split(".");
4129
+ if (parts.length !== 4) return null;
4130
+ let result = 0;
4131
+ for (const part of parts) {
4132
+ const n = parseInt(part, 10);
4133
+ if (isNaN(n) || n < 0 || n > 255) return null;
4134
+ result = result << 8 | n;
4135
+ }
4136
+ return result >>> 0;
4027
4137
  }
4028
4138
  };
4029
4139
  var defaultConstraintEvaluator = new ConstraintEvaluator();