@absolutejs/auth 0.27.0-beta.8 → 0.27.0-beta.9

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.
@@ -1,9 +1,13 @@
1
- import type { KnownDeviceStore, LoginHistoryStore, RiskAction, RiskAssessment, RiskContext, RiskSignal } from './types';
1
+ import type { KnownDeviceStore, LoginHistoryStore, RiskAction, RiskAssessment, RiskContext, RiskSignal, RiskThresholds, RiskWeights, WeightedRiskAssessment } from './types';
2
2
  export type AdaptiveConfig = {
3
3
  historyLimit?: number;
4
4
  knownDeviceStore: KnownDeviceStore;
5
5
  loginHistoryStore: LoginHistoryStore;
6
6
  maxTravelKmh?: number;
7
+ offHours?: {
8
+ end: number;
9
+ start: number;
10
+ };
7
11
  rules?: Partial<Record<RiskSignal, RiskAction>>;
8
12
  velocityMaxAttempts?: number;
9
13
  velocityWindowMs?: number;
@@ -14,9 +18,17 @@ export declare const createRiskEngine: (config: AdaptiveConfig) => {
14
18
  recordAttempt: (context: RiskContext & {
15
19
  outcome: RiskAction;
16
20
  }) => Promise<void>;
21
+ scoreRisk: (context: RiskContext, options?: {
22
+ thresholds?: RiskThresholds;
23
+ weights?: RiskWeights;
24
+ }) => Promise<WeightedRiskAssessment>;
17
25
  trustDevice: (userId: string, deviceId: string, label?: string) => Promise<void>;
18
26
  };
19
27
  export declare const recordLoginAttempt: (config: AdaptiveConfig, context: RiskContext & {
20
28
  outcome: RiskAction;
21
29
  }) => Promise<void>;
30
+ export declare const scoreRisk: (config: AdaptiveConfig & {
31
+ thresholds?: RiskThresholds;
32
+ weights?: RiskWeights;
33
+ }, context: RiskContext) => Promise<WeightedRiskAssessment>;
22
34
  export declare const trustDevice: (config: AdaptiveConfig, userId: string, deviceId: string, label?: string) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ export type DeviceSignals = Record<string, unknown>;
2
+ export declare const fingerprintDevice: (signals: DeviceSignals) => Promise<string>;
@@ -1,5 +1,5 @@
1
1
  export type RiskAction = 'allow' | 'deny' | 'step_up';
2
- export type RiskSignal = 'impossible_travel' | 'new_country' | 'new_device' | 'velocity';
2
+ export type RiskSignal = 'impossible_travel' | 'new_country' | 'new_device' | 'off_hours' | 'proxy' | 'velocity';
3
3
  export type GeoPoint = {
4
4
  country?: string;
5
5
  latitude?: number;
@@ -9,6 +9,8 @@ export type RiskContext = {
9
9
  deviceId: string;
10
10
  geo?: GeoPoint;
11
11
  ipAddress?: string;
12
+ isProxy?: boolean;
13
+ localHour?: number;
12
14
  now?: number;
13
15
  userId: string;
14
16
  };
@@ -20,6 +22,16 @@ export type RiskAssessment = {
20
22
  action: RiskAction;
21
23
  reasons: RiskReason[];
22
24
  };
25
+ export type RiskWeights = Partial<Record<RiskSignal, number>>;
26
+ export type RiskThresholds = {
27
+ deny: number;
28
+ stepUp: number;
29
+ };
30
+ export type WeightedRiskAssessment = {
31
+ action: RiskAction;
32
+ reasons: RiskReason[];
33
+ score: number;
34
+ };
23
35
  export type KnownDevice = {
24
36
  deviceId: string;
25
37
  firstSeenAt: number;
@@ -0,0 +1,2 @@
1
+ import type { AuditEvent } from './types';
2
+ export declare const exportAuditCsv: (events: AuditEvent[]) => string;
@@ -15,4 +15,5 @@ export type AuditEventFilter = {
15
15
  export type AuditSink = {
16
16
  append: (event: AuditEvent) => Promise<void>;
17
17
  list?: (filter?: AuditEventFilter) => Promise<AuditEvent[]>;
18
+ prune?: (before: number) => Promise<number>;
18
19
  };
@@ -15,10 +15,17 @@ export type Subject = {
15
15
  subjectId: string;
16
16
  subjectType: string;
17
17
  };
18
+ export type ObjectQuery = {
19
+ relation: string;
20
+ resourceType: string;
21
+ subjectId: string;
22
+ subjectType: string;
23
+ };
18
24
  export declare const check: (config: FgaConfig, query: CheckQuery) => Promise<boolean>;
19
25
  export declare const createFgaEngine: (config: FgaConfig) => {
20
26
  check: (query: CheckQuery) => Promise<boolean>;
21
27
  deleteWarrant: (warrant: Warrant) => Promise<void>;
28
+ listObjects: (query: ObjectQuery) => Promise<string[]>;
22
29
  listSubjects: (query: {
23
30
  relation: string;
24
31
  resourceId: string;
@@ -27,6 +34,7 @@ export declare const createFgaEngine: (config: FgaConfig) => {
27
34
  writeWarrant: (warrant: Warrant) => Promise<void>;
28
35
  };
29
36
  export declare const deleteWarrant: (config: FgaConfig, warrant: Warrant) => Promise<void>;
37
+ export declare const listObjects: (config: FgaConfig, query: ObjectQuery) => Promise<string[]>;
30
38
  export declare const listSubjects: (config: FgaConfig, query: {
31
39
  relation: string;
32
40
  resourceId: string;
@@ -0,0 +1,2 @@
1
+ import type { FgaSchema } from './types';
2
+ export declare const parseSchema: (dsl: string) => FgaSchema;
@@ -9,6 +9,7 @@ export type Warrant = {
9
9
  export type WarrantStore = {
10
10
  deleteWarrant: (warrant: Warrant) => Promise<void>;
11
11
  listForResource: (resourceType: string, resourceId: string, relation: string) => Promise<Warrant[]>;
12
+ listResourceIds: (resourceType: string) => Promise<string[]>;
12
13
  saveWarrant: (warrant: Warrant) => Promise<void>;
13
14
  };
14
15
  export type RelationRule = {
package/dist/index.d.ts CHANGED
@@ -14712,6 +14712,7 @@ export { createInMemoryLockoutStore } from './lockout/inMemoryLockoutStore';
14712
14712
  export { createNeonLockoutStore, createPostgresLockoutStore, lockoutsTable } from './lockout/postgresLockoutStore';
14713
14713
  export { createRedisLockoutStore } from './lockout/redisLockoutStore';
14714
14714
  export type { RedisLike } from './stores/redis';
14715
+ export { exportAuditCsv } from './audit/export';
14715
14716
  export { createInMemoryAuditSink } from './audit/inMemoryAuditStore';
14716
14717
  export { auditEventsTable, createNeonAuditSink, createPostgresAuditSink } from './audit/postgresAuditStore';
14717
14718
  export * from './sso/types';
@@ -14736,10 +14737,12 @@ export type { DpopResult } from './oidc/dpop';
14736
14737
  export { createInMemoryAuthorizationCodeStore, createInMemoryOAuthClientStore, createInMemoryOidcRefreshTokenStore } from './oidc/inMemoryStores';
14737
14738
  export { createNeonAuthorizationCodeStore, createNeonOAuthClientStore, createNeonOidcRefreshTokenStore, createPostgresAuthorizationCodeStore, createPostgresOAuthClientStore, createPostgresOidcRefreshTokenStore, oauthClientsTable, oauthCodesTable, oauthRefreshTokensTable } from './oidc/postgresStores';
14738
14739
  export * from './adaptive/config';
14740
+ export * from './adaptive/fingerprint';
14739
14741
  export * from './adaptive/types';
14740
14742
  export { createInMemoryKnownDeviceStore, createInMemoryLoginHistoryStore } from './adaptive/inMemoryStores';
14741
14743
  export { createNeonKnownDeviceStore, createNeonLoginHistoryStore, createPostgresKnownDeviceStore, createPostgresLoginHistoryStore, knownDevicesTable, loginHistoryTable } from './adaptive/postgresStores';
14742
14744
  export * from './fga/config';
14745
+ export * from './fga/schema';
14743
14746
  export * from './fga/types';
14744
14747
  export { createInMemoryWarrantStore, warrantKey } from './fga/inMemoryStores';
14745
14748
  export { createNeonWarrantStore, createPostgresWarrantStore, warrantsTable } from './fga/postgresStores';
package/dist/index.js CHANGED
@@ -18769,6 +18769,7 @@ var createTamperEvidentSink = ({
18769
18769
  };
18770
18770
  return {
18771
18771
  list: sink.list,
18772
+ prune: sink.prune,
18772
18773
  append: async (event) => {
18773
18774
  await seed();
18774
18775
  const previousHash = lastHash ?? GENESIS;
@@ -19084,6 +19085,19 @@ var createRedisLockoutStore = (redis, keyPrefix = DEFAULT_PREFIX) => {
19084
19085
  }
19085
19086
  };
19086
19087
  };
19088
+ // src/audit/export.ts
19089
+ var CSV_HEADER = "at,type,userId,ip,organizationId,metadata";
19090
+ var escapeCsv = (value) => /[",\n\r]/u.test(value) ? `"${value.replace(/"/gu, '""')}"` : value;
19091
+ var toRow = (event) => [
19092
+ new Date(event.at).toISOString(),
19093
+ event.type,
19094
+ event.userId ?? "",
19095
+ event.ip ?? "",
19096
+ event.organizationId ?? "",
19097
+ event.metadata ? JSON.stringify(event.metadata) : ""
19098
+ ].map(escapeCsv).join(",");
19099
+ var exportAuditCsv = (events) => [CSV_HEADER, ...events.map(toRow)].join(`
19100
+ `);
19087
19101
  // src/audit/inMemoryAuditStore.ts
19088
19102
  var createInMemoryAuditSink = () => {
19089
19103
  const events = [];
@@ -19096,6 +19110,13 @@ var createInMemoryAuditSink = () => {
19096
19110
  const ordered = [...matched].sort((left, right) => right.at - left.at);
19097
19111
  const limited = filter?.limit === undefined ? ordered : ordered.slice(0, filter.limit);
19098
19112
  return limited.map((event) => ({ ...event }));
19113
+ },
19114
+ prune: async (before) => {
19115
+ const kept = events.filter((event) => event.at >= before);
19116
+ const removed = events.length - kept.length;
19117
+ events.length = 0;
19118
+ events.push(...kept);
19119
+ return removed;
19099
19120
  }
19100
19121
  };
19101
19122
  };
@@ -19137,6 +19158,10 @@ var createPostgresAuditSink = (db) => ({
19137
19158
  list: async (filter) => {
19138
19159
  const rows = await db.select().from(auditEventsTable).where(filter?.userId ? eq(auditEventsTable.user_id, filter.userId) : undefined).orderBy(desc(auditEventsTable.at_ms)).limit(filter?.limit ?? DEFAULT_AUDIT_LIMIT);
19139
19160
  return rows.map(toEvent);
19161
+ },
19162
+ prune: async (before) => {
19163
+ const deleted = await db.delete(auditEventsTable).where(lt(auditEventsTable.at_ms, before)).returning({ id: auditEventsTable.id });
19164
+ return deleted.length;
19140
19165
  }
19141
19166
  });
19142
19167
  // src/scim/inMemoryScimTokenStore.ts
@@ -19573,8 +19598,22 @@ var DEFAULT_RULE_ACTIONS = {
19573
19598
  impossible_travel: "deny",
19574
19599
  new_country: "step_up",
19575
19600
  new_device: "step_up",
19601
+ off_hours: "allow",
19602
+ proxy: "step_up",
19576
19603
  velocity: "deny"
19577
19604
  };
19605
+ var DEFAULT_RISK_WEIGHTS = {
19606
+ impossible_travel: 80,
19607
+ new_country: 25,
19608
+ new_device: 20,
19609
+ off_hours: 10,
19610
+ proxy: 30,
19611
+ velocity: 80
19612
+ };
19613
+ var DEFAULT_OFF_HOURS_START = 0;
19614
+ var DEFAULT_OFF_HOURS_END = 6;
19615
+ var DEFAULT_DENY_SCORE = 80;
19616
+ var DEFAULT_STEP_UP_SCORE = 40;
19578
19617
  var toRadians = (degrees) => degrees * Math.PI / DEGREES_PER_HALF_TURN;
19579
19618
  var haversineKm = (start, end) => {
19580
19619
  if (start.latitude === undefined || start.longitude === undefined || end.latitude === undefined || end.longitude === undefined) {
@@ -19588,32 +19627,44 @@ var haversineKm = (start, end) => {
19588
19627
  return HALF * EARTH_RADIUS_KM * Math.asin(Math.sqrt(factor));
19589
19628
  };
19590
19629
  var mostSevere2 = (reasons) => reasons.reduce((worst, reason) => ACTION_SEVERITY2[reason.action] > ACTION_SEVERITY2[worst] ? reason.action : worst, "allow");
19591
- var assessRisk = async (config, context) => {
19630
+ var isWithinOffHours = (hour, range) => {
19631
+ const start = range?.start ?? DEFAULT_OFF_HOURS_START;
19632
+ const end = range?.end ?? DEFAULT_OFF_HOURS_END;
19633
+ if (start <= end)
19634
+ return hour >= start && hour < end;
19635
+ return hour >= start || hour < end;
19636
+ };
19637
+ var actionForScore = (score, thresholds) => {
19638
+ const deny = "deny";
19639
+ const stepUp = "step_up";
19640
+ const allow = "allow";
19641
+ if (score >= thresholds.deny)
19642
+ return deny;
19643
+ if (score >= thresholds.stepUp)
19644
+ return stepUp;
19645
+ return allow;
19646
+ };
19647
+ var detectSignals = async (config, context) => {
19592
19648
  const {
19593
19649
  historyLimit = DEFAULT_HISTORY_LIMIT,
19594
19650
  knownDeviceStore,
19595
19651
  loginHistoryStore,
19596
19652
  maxTravelKmh = DEFAULT_MAX_TRAVEL_KMH,
19597
- rules,
19653
+ offHours,
19598
19654
  velocityMaxAttempts = DEFAULT_VELOCITY_MAX_ATTEMPTS,
19599
19655
  velocityWindowMs = DEFAULT_VELOCITY_WINDOW_MS
19600
19656
  } = config;
19601
19657
  const now = context.now ?? Date.now();
19602
- const actions = {
19603
- ...DEFAULT_RULE_ACTIONS,
19604
- ...rules
19605
- };
19606
- const reasons = [];
19658
+ const fired = [];
19607
19659
  const [device, history] = await Promise.all([
19608
19660
  knownDeviceStore.findDevice(context.userId, context.deviceId),
19609
19661
  loginHistoryStore.listRecent(context.userId, historyLimit)
19610
19662
  ]);
19611
- if (device === undefined || !device.trusted) {
19612
- reasons.push({ action: actions.new_device, signal: "new_device" });
19613
- }
19663
+ if (device === undefined || !device.trusted)
19664
+ fired.push("new_device");
19614
19665
  const country = context.geo?.country;
19615
19666
  if (country !== undefined && history.length > 0 && !history.some((attempt) => attempt.country === country)) {
19616
- reasons.push({ action: actions.new_country, signal: "new_country" });
19667
+ fired.push("new_country");
19617
19668
  }
19618
19669
  const [previous] = history;
19619
19670
  const traveledKm = previous !== undefined && context.geo !== undefined ? haversineKm({
@@ -19622,20 +19673,34 @@ var assessRisk = async (config, context) => {
19622
19673
  }, context.geo) : undefined;
19623
19674
  const hours = previous === undefined ? 0 : (now - previous.timestamp) / MILLISECONDS_IN_AN_HOUR;
19624
19675
  if (traveledKm !== undefined && hours > 0 && traveledKm / hours > maxTravelKmh) {
19625
- reasons.push({
19626
- action: actions.impossible_travel,
19627
- signal: "impossible_travel"
19628
- });
19676
+ fired.push("impossible_travel");
19629
19677
  }
19630
19678
  const recentCount = history.filter((attempt) => now - attempt.timestamp <= velocityWindowMs).length;
19631
- if (recentCount >= velocityMaxAttempts) {
19632
- reasons.push({ action: actions.velocity, signal: "velocity" });
19679
+ if (recentCount >= velocityMaxAttempts)
19680
+ fired.push("velocity");
19681
+ if (context.isProxy === true)
19682
+ fired.push("proxy");
19683
+ if (context.localHour !== undefined && isWithinOffHours(context.localHour, offHours)) {
19684
+ fired.push("off_hours");
19633
19685
  }
19686
+ return fired;
19687
+ };
19688
+ var assessRisk = async (config, context) => {
19689
+ const actions = {
19690
+ ...DEFAULT_RULE_ACTIONS,
19691
+ ...config.rules
19692
+ };
19693
+ const fired = await detectSignals(config, context);
19694
+ const reasons = fired.map((signal) => ({
19695
+ action: actions[signal],
19696
+ signal
19697
+ }));
19634
19698
  return { action: mostSevere2(reasons), reasons };
19635
19699
  };
19636
19700
  var createRiskEngine = (config) => ({
19637
19701
  assessRisk: (context) => assessRisk(config, context),
19638
19702
  recordAttempt: (context) => recordLoginAttempt(config, context),
19703
+ scoreRisk: (context, options) => scoreRisk({ ...config, ...options }, context),
19639
19704
  trustDevice: (userId, deviceId, label) => trustDevice(config, userId, deviceId, label)
19640
19705
  });
19641
19706
  var recordLoginAttempt = async (config, context) => {
@@ -19661,6 +19726,22 @@ var recordLoginAttempt = async (config, context) => {
19661
19726
  userId: context.userId
19662
19727
  });
19663
19728
  };
19729
+ var scoreRisk = async (config, context) => {
19730
+ const weights = {
19731
+ ...DEFAULT_RISK_WEIGHTS,
19732
+ ...config.weights
19733
+ };
19734
+ const defaultThresholds = {
19735
+ deny: DEFAULT_DENY_SCORE,
19736
+ stepUp: DEFAULT_STEP_UP_SCORE
19737
+ };
19738
+ const thresholds = config.thresholds ?? defaultThresholds;
19739
+ const fired = await detectSignals(config, context);
19740
+ const score = fired.reduce((sum, signal) => sum + weights[signal], 0);
19741
+ const action = actionForScore(score, thresholds);
19742
+ const reasons = fired.map((signal) => ({ action, signal }));
19743
+ return { action, reasons, score };
19744
+ };
19664
19745
  var trustDevice = async (config, userId, deviceId, label) => {
19665
19746
  const now = Date.now();
19666
19747
  const existing = await config.knownDeviceStore.findDevice(userId, deviceId);
@@ -19673,6 +19754,9 @@ var trustDevice = async (config, userId, deviceId, label) => {
19673
19754
  userId
19674
19755
  });
19675
19756
  };
19757
+ // src/adaptive/fingerprint.ts
19758
+ var canonical = (signals) => JSON.stringify(signals, (_key, value) => value === null || typeof value !== "object" || Array.isArray(value) ? value : Object.fromEntries(Object.entries(value).sort((left, right) => left[0].localeCompare(right[0]))));
19759
+ var fingerprintDevice = (signals) => hashToken(canonical(signals));
19676
19760
  // src/adaptive/inMemoryStores.ts
19677
19761
  var deviceKey = (userId, deviceId) => `${userId}:${deviceId}`;
19678
19762
  var createInMemoryKnownDeviceStore = () => {
@@ -19872,16 +19956,95 @@ var expandRule = async (config, resourceType, resourceId, relation, rule, depth,
19872
19956
  var createFgaEngine = (config) => ({
19873
19957
  check: (query) => check(config, query),
19874
19958
  deleteWarrant: (warrant) => deleteWarrant(config, warrant),
19959
+ listObjects: (query) => listObjects(config, query),
19875
19960
  listSubjects: (query) => listSubjects(config, query),
19876
19961
  writeWarrant: (warrant) => writeWarrant(config, warrant)
19877
19962
  });
19878
19963
  var deleteWarrant = (config, warrant) => config.warrantStore.deleteWarrant(warrant);
19964
+ var listObjects = async (config, query) => {
19965
+ const candidates = await config.warrantStore.listResourceIds(query.resourceType);
19966
+ const allowed = await Promise.all(candidates.map((resourceId) => check(config, {
19967
+ relation: query.relation,
19968
+ resourceId,
19969
+ resourceType: query.resourceType,
19970
+ subjectId: query.subjectId,
19971
+ subjectType: query.subjectType
19972
+ })));
19973
+ return candidates.filter((_resourceId, index) => allowed[index] === true);
19974
+ };
19879
19975
  var listSubjects = async (config, query) => {
19880
19976
  const found = new Map;
19881
19977
  await expand(config, query.resourceType, query.resourceId, query.relation, config.maxDepth ?? DEFAULT_MAX_DEPTH, found, new Set);
19882
19978
  return [...found.values()];
19883
19979
  };
19884
19980
  var writeWarrant = (config, warrant) => config.warrantStore.saveWarrant(warrant);
19981
+ // src/fga/schema.ts
19982
+ var TYPE_PATTERN = /^type\s+(\w+)$/u;
19983
+ var DEFINE_PATTERN = /^define\s+(\w+)\s*:\s*(.+)$/u;
19984
+ var FROM_PATTERN = /^(\w+)\s+from\s+(\w+)$/u;
19985
+ var OR_SEPARATOR = /\s+or\s+/u;
19986
+ var parseTerm = (term) => {
19987
+ const trimmed = term.trim();
19988
+ if (trimmed.startsWith("[")) {
19989
+ const rule2 = { kind: "self" };
19990
+ return rule2;
19991
+ }
19992
+ const fromMatch = FROM_PATTERN.exec(trimmed);
19993
+ if (fromMatch) {
19994
+ const [, relation, viaRelation] = fromMatch;
19995
+ const rule2 = {
19996
+ kind: "tupleToUserset",
19997
+ relation: relation ?? "",
19998
+ viaRelation: viaRelation ?? ""
19999
+ };
20000
+ return rule2;
20001
+ }
20002
+ const rule = { kind: "computedUserset", relation: trimmed };
20003
+ return rule;
20004
+ };
20005
+ var parseExpression = (expression) => {
20006
+ const terms = expression.split(OR_SEPARATOR).map(parseTerm);
20007
+ const [first] = terms;
20008
+ if (terms.length === 1 && first)
20009
+ return first;
20010
+ const rule = { kind: "union", rules: terms };
20011
+ return rule;
20012
+ };
20013
+ var applyType = (schema, line2) => {
20014
+ const match = TYPE_PATTERN.exec(line2);
20015
+ if (!match)
20016
+ return;
20017
+ const [, name] = match;
20018
+ if (name)
20019
+ schema[name] = {};
20020
+ return name;
20021
+ };
20022
+ var applyDefine = (target, line2) => {
20023
+ if (!target)
20024
+ return;
20025
+ const match = DEFINE_PATTERN.exec(line2);
20026
+ if (!match)
20027
+ return;
20028
+ const [, relation, expression] = match;
20029
+ if (relation && expression)
20030
+ target[relation] = parseExpression(expression);
20031
+ };
20032
+ var parseSchema = (dsl) => {
20033
+ const schema = {};
20034
+ let currentType;
20035
+ for (const rawLine of dsl.split(`
20036
+ `)) {
20037
+ const line2 = rawLine.trim();
20038
+ if (line2 === "" || line2.startsWith("#") || line2 === "relations")
20039
+ continue;
20040
+ const typeName = applyType(schema, line2);
20041
+ currentType = typeName ?? currentType;
20042
+ if (typeName !== undefined)
20043
+ continue;
20044
+ applyDefine(currentType ? schema[currentType] : undefined, line2);
20045
+ }
20046
+ return schema;
20047
+ };
19885
20048
  // src/fga/inMemoryStores.ts
19886
20049
  var createInMemoryWarrantStore = () => {
19887
20050
  const warrants = new Map;
@@ -19890,6 +20053,9 @@ var createInMemoryWarrantStore = () => {
19890
20053
  warrants.delete(warrantKey(warrant));
19891
20054
  },
19892
20055
  listForResource: async (resourceType, resourceId, relation) => [...warrants.values()].filter((warrant) => warrant.resourceType === resourceType && warrant.resourceId === resourceId && warrant.relation === relation),
20056
+ listResourceIds: async (resourceType) => [
20057
+ ...new Set([...warrants.values()].filter((warrant) => warrant.resourceType === resourceType).map((warrant) => warrant.resourceId))
20058
+ ],
19893
20059
  saveWarrant: async (warrant) => {
19894
20060
  warrants.set(warrantKey(warrant), { ...warrant });
19895
20061
  }
@@ -19924,6 +20090,10 @@ var createPostgresWarrantStore = (db) => ({
19924
20090
  const rows = await db.select().from(warrantsTable).where(and(eq(warrantsTable.resource_type, resourceType), eq(warrantsTable.resource_id, resourceId), eq(warrantsTable.relation, relation)));
19925
20091
  return rows.map(toWarrant);
19926
20092
  },
20093
+ listResourceIds: async (resourceType) => {
20094
+ const rows = await db.selectDistinct({ resourceId: warrantsTable.resource_id }).from(warrantsTable).where(eq(warrantsTable.resource_type, resourceType));
20095
+ return rows.map((row) => row.resourceId);
20096
+ },
19927
20097
  saveWarrant: async (warrant) => {
19928
20098
  await db.insert(warrantsTable).values({
19929
20099
  id: warrantKey(warrant),
@@ -20751,6 +20921,7 @@ export {
20751
20921
  sessionStore,
20752
20922
  sessionRoutes,
20753
20923
  sessionCleanup,
20924
+ scoreRisk,
20754
20925
  scopeRequiredProviderOptions,
20755
20926
  scimTokensTable,
20756
20927
  scimRoutes,
@@ -20781,6 +20952,7 @@ export {
20781
20952
  pkceProviderOptions,
20782
20953
  passwordlessTokensTable,
20783
20954
  passwordlessRoutes,
20955
+ parseSchema,
20784
20956
  organizationsTable,
20785
20957
  organizationRoutes,
20786
20958
  organizationMembershipsTable,
@@ -20802,6 +20974,7 @@ export {
20802
20974
  listUserOrganizations,
20803
20975
  listSubjects,
20804
20976
  listRingSessions,
20977
+ listObjects,
20805
20978
  knownDevicesTable,
20806
20979
  jwkThumbprint,
20807
20980
  issueTokenSet,
@@ -20835,7 +21008,9 @@ export {
20835
21008
  generateSecureToken,
20836
21009
  generateEncryptionKey,
20837
21010
  generateBackupCodes,
21011
+ fingerprintDevice,
20838
21012
  extractPropFromIdentity,
21013
+ exportAuditCsv,
20839
21014
  exchangeToken,
20840
21015
  exchangeClientCredentials,
20841
21016
  evaluatePassword,
@@ -20999,5 +21174,5 @@ export {
20999
21174
  AuthIdentityConflictError
21000
21175
  };
21001
21176
 
21002
- //# debugId=B234E4311897F15C64756E2164756E21
21177
+ //# debugId=22C6F88FE2A9D7F764756E2164756E21
21003
21178
  //# sourceMappingURL=index.js.map