@prosopo/database 4.0.16 → 4.0.18
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/.turbo/turbo-build$colon$cjs.log +3 -3
- package/.turbo/turbo-build$colon$tsc.log +16 -16
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +36 -0
- package/dist/cjs/databases/provider.cjs +36 -70
- package/dist/databases/provider.d.ts +2 -3
- package/dist/databases/provider.d.ts.map +1 -1
- package/dist/databases/provider.js +37 -71
- package/dist/databases/provider.js.map +1 -1
- package/dist/tests/integration/commitmentRecordProjection.integration.test.d.ts +2 -0
- package/dist/tests/integration/commitmentRecordProjection.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/commitmentRecordProjection.integration.test.js +178 -0
- package/dist/tests/integration/commitmentRecordProjection.integration.test.js.map +1 -0
- package/dist/tests/integration/projectionContract.d.ts +9 -0
- package/dist/tests/integration/projectionContract.d.ts.map +1 -0
- package/dist/tests/integration/projectionContract.js +20 -0
- package/dist/tests/integration/projectionContract.js.map +1 -0
- package/dist/tests/integration/projectionContracts.integration.test.d.ts +2 -0
- package/dist/tests/integration/projectionContracts.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/projectionContracts.integration.test.js +190 -0
- package/dist/tests/integration/projectionContracts.integration.test.js.map +1 -0
- package/package.json +9 -9
- package/dist/tests/integration/randomSamplingPerformance.integration.test.d.ts +0 -2
- package/dist/tests/integration/randomSamplingPerformance.integration.test.d.ts.map +0 -1
- package/dist/tests/integration/randomSamplingPerformance.integration.test.js +0 -248
- package/dist/tests/integration/randomSamplingPerformance.integration.test.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/database@4.0.
|
|
2
|
+
> @prosopo/database@4.0.18 build:cjs
|
|
3
3
|
> NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
|
|
4
4
|
|
|
5
5
|
ViteCommonJSConfig: .
|
|
@@ -51,6 +51,6 @@ dist/cjs/base/mongo.cjs 3.77 kB │ gzip: 1.29 kB
|
|
|
51
51
|
dist/cjs/databases/centralDbStreamer.cjs 5.29 kB │ gzip: 1.30 kB
|
|
52
52
|
dist/cjs/databases/captcha.cjs 7.36 kB │ gzip: 2.17 kB
|
|
53
53
|
dist/cjs/redisCache.cjs 15.77 kB │ gzip: 4.54 kB
|
|
54
|
-
dist/cjs/databases/provider.cjs
|
|
54
|
+
dist/cjs/databases/provider.cjs 60.74 kB │ gzip: 12.32 kB
|
|
55
55
|
|
|
56
|
-
[32m✓ built in
|
|
56
|
+
[32m✓ built in 99ms[39m
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/database@4.0.
|
|
2
|
+
> @prosopo/database@4.0.18 build:tsc
|
|
3
3
|
> tsc --build --verbose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
10:10:30 PM - Projects in this build:
|
|
6
6
|
* ../../dev/config/tsconfig.json
|
|
7
7
|
* ../locale/tsconfig.json
|
|
8
8
|
* ../util/tsconfig.json
|
|
@@ -17,31 +17,31 @@
|
|
|
17
17
|
* ../types-database/tsconfig.json
|
|
18
18
|
* tsconfig.json
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
10:10:30 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
10:10:30 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
10:10:30 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
10:10:30 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
10:10:30 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
10:10:30 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
10:10:30 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/error.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
10:10:30 PM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/tsconfig.tsbuildinfo'
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
10:10:30 PM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/tsconfig.tsbuildinfo'
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
10:10:30 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
10:10:30 PM - Project '../user-access-policy/tsconfig.json' is up to date because newest input '../user-access-policy/src/transformRule.ts' is older than output '../user-access-policy/tsconfig.tsbuildinfo'
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
10:10:30 PM - Project '../types-database/tsconfig.json' is up to date because newest input '../types-database/src/types.test-d.ts' is older than output '../types-database/tsconfig.tsbuildinfo'
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
10:10:30 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
10:10:30 PM - Building project '/home/runner/work/captcha/captcha/packages/database/tsconfig.json'...
|
|
47
47
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/database@4.0.
|
|
2
|
+
> @prosopo/database@4.0.18 build
|
|
3
3
|
> npm run build:cross-env -- --mode ${NODE_ENV:-development}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @prosopo/database@4.0.
|
|
6
|
+
> @prosopo/database@4.0.18 build:cross-env
|
|
7
7
|
> vite build --config vite.esm.config.ts --mode production
|
|
8
8
|
|
|
9
9
|
ViteEsmConfig: .
|
|
@@ -55,6 +55,6 @@ dist/base/mongo.js 3.52 kB │ gzip: 1.20 kB
|
|
|
55
55
|
dist/databases/centralDbStreamer.js 5.23 kB │ gzip: 1.28 kB
|
|
56
56
|
dist/databases/captcha.js 7.28 kB │ gzip: 2.16 kB
|
|
57
57
|
dist/redisCache.js 15.71 kB │ gzip: 4.53 kB
|
|
58
|
-
dist/databases/provider.js
|
|
58
|
+
dist/databases/provider.js 59.45 kB │ gzip: 12.33 kB
|
|
59
59
|
|
|
60
|
-
[32m✓ built in
|
|
60
|
+
[32m✓ built in 98ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @prosopo/database
|
|
2
2
|
|
|
3
|
+
## 4.0.18
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- a2f4b13: Extend `getDappUserCommitmentById` and `getDappUserCommitmentByAccount` projections to include every field that the downstream verify path (`verifyImageCaptchaSolution`) reads off the returned solution — `behavioralDataPacked`, `deviceCapability`, `coords`, plus (for the by-account fallback) `userAccount`, `dappAccount`, `headers`, `ipInfo`, `sessionId`, `serverChecked`, `ipAddress`, `submittedAtTimestamp`. Both methods now share `DAPP_USER_COMMITMENT_PROJECTION`.
|
|
7
|
+
|
|
8
|
+
Root cause: same class as #3107 (`getSessionRecordBySessionId` missing tcp-probe fields). `getDappUserCommitmentById` had a 13-field projection that omitted `behavioralDataPacked`, `deviceCapability`, and `coords`. `getDappUserCommitmentByAccount` projected only `{_id: 0, result: 1}`, so on that branch every field beyond `result` landed as `undefined` at the caller. Any downstream code path that read a stripped field silently degraded.
|
|
9
|
+
|
|
10
|
+
Guard: adds `commitmentRecordProjection.integration.test.ts` — persists a full commitment, fetches via both methods, asserts each field the verify path reads round-trips and that both methods return the same shape.
|
|
11
|
+
- 179a2b0: Add reusable projection-contract test scaffold for `ProviderDatabase` mongo fetch methods.
|
|
12
|
+
|
|
13
|
+
`packages/database/src/tests/integration/projectionContract.ts` exports `testProjectionContract`, a vitest helper that pins a (projection method, consumer) pair: insert a fully-populated fixture, fetch via the method under test, assert every field the consumer reads survives the projection. `packages/database/src/tests/integration/projectionContracts.integration.test.ts` wires initial contracts for `getPowCaptchaRecordByChallenge`, `getPuzzleCaptchaRecordByChallenge`, and `getClientRecord`.
|
|
14
|
+
|
|
15
|
+
Motivation: same class of bug keeps landing (`getSessionRecordBySessionId` missing tcp-probe fields — #3107; `getDappUserCommitmentBy{Id,Account}` missing verify-path fields — #3116). Mongo projections narrow at write time and stay narrow, while downstream consumers add new field reads over time; TypeScript can't catch the mismatch because the return type is the full record, not the projected subset. This scaffold pins the contract per method and fails a targeted assertion the moment a projection stops covering what the consumer reads.
|
|
16
|
+
|
|
17
|
+
Adding a new contract when a new projected fetch method lands, or extending the `consumerReads` manifest when a consumer starts reading a new field, is now the drift-prevention convention. `commitmentRecordProjection.integration.test.ts` and `sessionRecordProjection.integration.test.ts` remain as bespoke regression guards; the scaffold is additive, not a replacement.
|
|
18
|
+
- Updated dependencies [68a9b41]
|
|
19
|
+
- Updated dependencies [ce5a3d7]
|
|
20
|
+
- @prosopo/types@5.2.6
|
|
21
|
+
- @prosopo/user-access-policy@3.12.25
|
|
22
|
+
- @prosopo/util@3.3.7
|
|
23
|
+
- @prosopo/common@3.1.51
|
|
24
|
+
- @prosopo/logger@2.0.7
|
|
25
|
+
- @prosopo/redis-client@1.0.33
|
|
26
|
+
- @prosopo/types-database@5.1.11
|
|
27
|
+
|
|
28
|
+
## 4.0.17
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- dfc1fa6: Two provider-DB latency fixes.
|
|
32
|
+
|
|
33
|
+
**Pin the pending-stage sweep to its compound partial index.** `getUnstoredDappUserCommitments`, `getUnstoredDappUserPoWCommitments`, and `getUnstoredSessionRecords` now call `.hint("pendingStage_partial")`. Observed post-index-fix on 2026-08-21: mongo's planner sometimes picked plain `IXSCAN {_id:1}` over the compound `{pendingStage:1, _id:1}` for `find({pendingStage:true}).sort({_id:1})`, scanning the whole collection and filtering in memory until the 30s socket timeout killed the connection. Clearing the plan cache re-planned once but didn't prevent recurrence after future catalog changes — the hint makes the choice explicit and permanent.
|
|
34
|
+
|
|
35
|
+
**Remove local context-entropy computation.** Deletes `sampleContextEntropy` (the `$sample`-then-`$lookup` aggregation), `setClientContextEntropy`, `ClientTaskManager.calculateClientEntropy`, and the `setClientEntropy` scheduler + CLI registration. Was accounting for ~36 minutes of DB time every 6h against `powcaptchas` and `sessions` — the `$lookup` fanned out to 10 000 session reads per invocation to produce 75 sampled sessionIds. Same computation now runs off-provider in the external job-runner across the full record set; the provider keeps `getClientContextEntropy` for the DM's read path (the job-runner writes to the same `clientcontextentropies` collection).
|
|
36
|
+
- Updated dependencies [dfc1fa6]
|
|
37
|
+
- @prosopo/types-database@5.1.10
|
|
38
|
+
|
|
3
39
|
## 4.0.16
|
|
4
40
|
### Patch Changes
|
|
5
41
|
|
|
@@ -6,8 +6,6 @@ let _polkadot_util_is = require("@polkadot/util/is");
|
|
|
6
6
|
let _prosopo_redis_client = require("@prosopo/redis-client");
|
|
7
7
|
let _prosopo_user_access_policy_redis = require("@prosopo/user-access-policy/redis");
|
|
8
8
|
let _prosopo_util = require("@prosopo/util");
|
|
9
|
-
//#region src/databases/provider.ts
|
|
10
|
-
var TWENTY_FOUR_HOURS_IN_MS = 1440 * 60 * 1e3;
|
|
11
9
|
var MAX_DOMAIN_SUFFIX_CANDIDATES = 5;
|
|
12
10
|
var PROVIDER_TABLES = [
|
|
13
11
|
{
|
|
@@ -76,7 +74,7 @@ var PROVIDER_TABLES = [
|
|
|
76
74
|
schema: _prosopo_types_database.SpamEmailDomainRecordSchema
|
|
77
75
|
}
|
|
78
76
|
];
|
|
79
|
-
var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
77
|
+
var ProviderDatabase = class ProviderDatabase extends require_mongo.MongoDatabase {
|
|
80
78
|
constructor(options) {
|
|
81
79
|
super(options.mongo.url, options.mongo.dbname, options.mongo.authSource, options.logger);
|
|
82
80
|
this.options = options;
|
|
@@ -880,11 +878,20 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
880
878
|
* per page even with the right index; under a 1M-row pending backlog
|
|
881
879
|
* that hit multi-second query durations and thrashed the WT cache,
|
|
882
880
|
* dragging every co-tenant query with it.
|
|
881
|
+
*
|
|
882
|
+
* `.hint("pendingStage_partial")` pins the compound index against a
|
|
883
|
+
* planner regression seen in prod on 2026-08-21: on collections with
|
|
884
|
+
* both a plain `_id` index and the compound `{pendingStage:1, _id:1}`
|
|
885
|
+
* partial, the planner sometimes picks `_id` alone for
|
|
886
|
+
* `find({pendingStage:true}).sort({_id:1})` and scans the entire
|
|
887
|
+
* collection filtering in memory. Clearing the plan cache re-plans
|
|
888
|
+
* once but doesn't prevent the regression re-appearing after future
|
|
889
|
+
* catalog changes — the hint makes the choice explicit.
|
|
883
890
|
*/
|
|
884
891
|
async getUnstoredDappUserCommitments(limit = 1e3, afterId) {
|
|
885
892
|
const filter = { pendingStage: true };
|
|
886
893
|
if (afterId !== void 0) filter._id = { $gt: afterId };
|
|
887
|
-
return await this.tables?.commitment.find(filter).sort({ _id: 1 }).limit(limit).lean() || [];
|
|
894
|
+
return await this.tables?.commitment.find(filter).hint("pendingStage_partial").sort({ _id: 1 }).limit(limit).lean() || [];
|
|
888
895
|
}
|
|
889
896
|
/** @description Mark a list of captcha commits as stored.
|
|
890
897
|
*
|
|
@@ -970,7 +977,7 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
970
977
|
async getUnstoredDappUserPoWCommitments(limit = 1e3, afterId) {
|
|
971
978
|
const filter = { pendingStage: true };
|
|
972
979
|
if (afterId !== void 0) filter._id = { $gt: afterId };
|
|
973
|
-
return await this.tables?.powcaptcha.find(filter).sort({ _id: 1 }).limit(limit).lean() || [];
|
|
980
|
+
return await this.tables?.powcaptcha.find(filter).hint("pendingStage_partial").sort({ _id: 1 }).limit(limit).lean() || [];
|
|
974
981
|
}
|
|
975
982
|
/** @description Mark a list of PoW captcha commits as stored.
|
|
976
983
|
*
|
|
@@ -1299,7 +1306,7 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
1299
1306
|
getUnstoredSessionRecords(limit = 1e3, afterId) {
|
|
1300
1307
|
const filter = { pendingStage: true };
|
|
1301
1308
|
if (afterId !== void 0) filter._id = { $gt: afterId };
|
|
1302
|
-
return Promise.resolve(this.tables?.session).then((tbl) => tbl?.find(filter).sort({ _id: 1 }).limit(limit).lean()).then((docs) => docs || []);
|
|
1309
|
+
return Promise.resolve(this.tables?.session).then((tbl) => tbl?.find(filter).hint("pendingStage_partial").sort({ _id: 1 }).limit(limit).lean()).then((docs) => docs || []);
|
|
1303
1310
|
}
|
|
1304
1311
|
/** Mark a list of session records as stored.
|
|
1305
1312
|
*
|
|
@@ -1455,13 +1462,8 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
1455
1462
|
commitmentId
|
|
1456
1463
|
} });
|
|
1457
1464
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
* @param commitmentId
|
|
1461
|
-
*/
|
|
1462
|
-
async getDappUserCommitmentById(commitmentId) {
|
|
1463
|
-
const filter = { id: commitmentId };
|
|
1464
|
-
const doc = await this.tables?.commitment?.findOne(filter, {
|
|
1465
|
+
static {
|
|
1466
|
+
this.DAPP_USER_COMMITMENT_PROJECTION = {
|
|
1465
1467
|
id: 1,
|
|
1466
1468
|
result: 1,
|
|
1467
1469
|
serverChecked: 1,
|
|
@@ -1474,8 +1476,19 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
1474
1476
|
userAccount: 1,
|
|
1475
1477
|
dappAccount: 1,
|
|
1476
1478
|
headers: 1,
|
|
1477
|
-
ipInfo: 1
|
|
1478
|
-
|
|
1479
|
+
ipInfo: 1,
|
|
1480
|
+
behavioralDataPacked: 1,
|
|
1481
|
+
deviceCapability: 1,
|
|
1482
|
+
coords: 1
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* @description Get dapp user commitment by user account
|
|
1487
|
+
* @param commitmentId
|
|
1488
|
+
*/
|
|
1489
|
+
async getDappUserCommitmentById(commitmentId) {
|
|
1490
|
+
const filter = { id: commitmentId };
|
|
1491
|
+
const doc = await this.tables?.commitment?.findOne(filter, ProviderDatabase.DAPP_USER_COMMITMENT_PROJECTION).lean();
|
|
1479
1492
|
return doc ? doc : void 0;
|
|
1480
1493
|
}
|
|
1481
1494
|
/**
|
|
@@ -1488,10 +1501,7 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
1488
1501
|
userAccount,
|
|
1489
1502
|
dappAccount
|
|
1490
1503
|
};
|
|
1491
|
-
const docs = await this.tables?.commitment?.find(filter, {
|
|
1492
|
-
_id: 0,
|
|
1493
|
-
result: 1
|
|
1494
|
-
}, { sort: { _id: -1 } }).lean();
|
|
1504
|
+
const docs = await this.tables?.commitment?.find(filter, ProviderDatabase.DAPP_USER_COMMITMENT_PROJECTION, { sort: { _id: -1 } }).lean();
|
|
1495
1505
|
return docs ? docs : [];
|
|
1496
1506
|
}
|
|
1497
1507
|
/**
|
|
@@ -1771,21 +1781,14 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
1771
1781
|
return (await this.tables?.decisionMachine.deleteMany({}))?.deletedCount ?? 0;
|
|
1772
1782
|
}
|
|
1773
1783
|
/**
|
|
1774
|
-
* @description set client context-specific entropy
|
|
1775
|
-
*/
|
|
1776
|
-
async setClientContextEntropy(account, contextType, entropy) {
|
|
1777
|
-
const filter = {
|
|
1778
|
-
account,
|
|
1779
|
-
contextType
|
|
1780
|
-
};
|
|
1781
|
-
await this.tables?.clientContextEntropy.updateOne(filter, { $set: {
|
|
1782
|
-
account,
|
|
1783
|
-
contextType,
|
|
1784
|
-
entropy
|
|
1785
|
-
} }, { upsert: true });
|
|
1786
|
-
}
|
|
1787
|
-
/**
|
|
1788
1784
|
* @description get client context-specific entropy
|
|
1785
|
+
*
|
|
1786
|
+
* Read-only. The `clientcontextentropies` collection is populated
|
|
1787
|
+
* externally by the job-runner sweep — the provider used to compute
|
|
1788
|
+
* entropy locally via `sampleContextEntropy` + `setClientContextEntropy`
|
|
1789
|
+
* on a scheduled task, but that path was pulled 2026-08-21 (the sweep
|
|
1790
|
+
* aggregation was ~36 minutes of DB time per 6h, and the same
|
|
1791
|
+
* computation now runs off-provider across the full record set).
|
|
1789
1792
|
*/
|
|
1790
1793
|
async getClientContextEntropy(account, contextType) {
|
|
1791
1794
|
const filter = {
|
|
@@ -1795,43 +1798,6 @@ var ProviderDatabase = class extends require_mongo.MongoDatabase {
|
|
|
1795
1798
|
const doc = await this.tables?.clientContextEntropy.findOne(filter).lean();
|
|
1796
1799
|
return doc ? doc.entropy : void 0;
|
|
1797
1800
|
}
|
|
1798
|
-
/** Sample captcha records from the database for a specific context */
|
|
1799
|
-
async sampleContextEntropy(sampleSize, siteKey, contextType) {
|
|
1800
|
-
const size = sampleSize ? Math.abs(Math.trunc(sampleSize)) : 1;
|
|
1801
|
-
const max = 1e4;
|
|
1802
|
-
if (size > max) throw new _prosopo_common.ProsopoDBError("DATABASE.CAPTCHA_SAMPLE_SIZE_EXCEEDED", { context: {
|
|
1803
|
-
failedFuncName: this.sampleContextEntropy.name,
|
|
1804
|
-
sampleSize
|
|
1805
|
-
} });
|
|
1806
|
-
const pipeline = [
|
|
1807
|
-
{ $match: {
|
|
1808
|
-
dappAccount: siteKey,
|
|
1809
|
-
requestedAtTimestamp: { $gt: new Date((/* @__PURE__ */ new Date()).getTime() - TWENTY_FOUR_HOURS_IN_MS) }
|
|
1810
|
-
} },
|
|
1811
|
-
{ $sample: { size: max } },
|
|
1812
|
-
{ $lookup: {
|
|
1813
|
-
from: "sessions",
|
|
1814
|
-
localField: "sessionId",
|
|
1815
|
-
foreignField: "sessionId",
|
|
1816
|
-
as: "sessionData"
|
|
1817
|
-
} },
|
|
1818
|
-
{ $unwind: {
|
|
1819
|
-
path: "$sessionData",
|
|
1820
|
-
preserveNullAndEmptyArrays: false
|
|
1821
|
-
} }
|
|
1822
|
-
];
|
|
1823
|
-
if (contextType === _prosopo_types.ContextType.Webview) pipeline.push({ $match: { "sessionData.webView": true } });
|
|
1824
|
-
else if (contextType === _prosopo_types.ContextType.Default) pipeline.push({ $match: { "sessionData.webView": false } });
|
|
1825
|
-
pipeline.push({ $sample: { size } }, { $project: {
|
|
1826
|
-
_id: 0,
|
|
1827
|
-
sessionId: 1
|
|
1828
|
-
} });
|
|
1829
|
-
const docs = await this.tables?.powcaptcha.aggregate(pipeline);
|
|
1830
|
-
if (docs?.length === 0) return [];
|
|
1831
|
-
return (await Promise.all(docs.map(async (doc) => {
|
|
1832
|
-
if (doc.sessionId) return (await this.getSessionRecordBySessionId(doc.sessionId))?.decryptedHeadHash;
|
|
1833
|
-
}))).filter((headHash) => headHash !== void 0);
|
|
1834
|
-
}
|
|
1835
1801
|
async getSpamEmailDomain(domain) {
|
|
1836
1802
|
if (!this.tables?.spamEmailDomain) throw new _prosopo_common.ProsopoDBError("DATABASE.DATABASE_IMPORT_ERROR", { context: { failedFuncName: this.getSpamEmailDomain.name } });
|
|
1837
1803
|
const suffixCandidates = (0, _prosopo_util.buildDomainSuffixCandidates)(domain).slice(0, MAX_DOMAIN_SUFFIX_CANDIDATES);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from "@prosopo/logger";
|
|
2
2
|
import { type RedisConnection } from "@prosopo/redis-client";
|
|
3
|
-
import { type Captcha, type CaptchaResult, type CaptchaSolution, CaptchaStates, type CompositeIpAddress, ContextType, type Dataset, type DatasetBase, type DatasetWithIds, type DatasetWithIdsAndTree, type DecisionMachineArtifact, DecisionMachineKind, type DecisionMachineScope, type Hash, type IPInfoResponse, type PendingImageCaptchaRequest, type PoWChallengeComponents, type PoWChallengeId, type RequestHeaders, type ResultReason, type ScheduledTaskNames, type ScheduledTaskResult, type ScheduledTaskStatus, type Session, type SimdReadingsStage, type SolutionRecord, type UserCommitment } from "@prosopo/types";
|
|
3
|
+
import { type Captcha, type CaptchaResult, type CaptchaSolution, CaptchaStates, type CompositeIpAddress, type ContextType, type Dataset, type DatasetBase, type DatasetWithIds, type DatasetWithIdsAndTree, type DecisionMachineArtifact, DecisionMachineKind, type DecisionMachineScope, type Hash, type IPInfoResponse, type PendingImageCaptchaRequest, type PoWChallengeComponents, type PoWChallengeId, type RequestHeaders, type ResultReason, type ScheduledTaskNames, type ScheduledTaskResult, type ScheduledTaskStatus, type Session, type SimdReadingsStage, type SolutionRecord, type UserCommitment } from "@prosopo/types";
|
|
4
4
|
import type { SessionRecord } from "@prosopo/types-database";
|
|
5
5
|
import { type ClientRecord, type IProviderDatabase, type PoWCaptchaRecord, type PuzzleCaptchaRecord, type ScheduledTaskRecord, type SpamEmailDomainRecord, type Tables, type UserCommitmentRecord, type UserSolutionRecord } from "@prosopo/types-database";
|
|
6
6
|
import type { AccessRulesStorage } from "@prosopo/user-access-policy";
|
|
@@ -106,6 +106,7 @@ export declare class ProviderDatabase extends MongoDatabase implements IProvider
|
|
|
106
106
|
getDatasetIdWithSolvedCaptchasOfSizeN(solvedCaptchaCount: number): Promise<string>;
|
|
107
107
|
getRandomSolvedCaptchasFromSingleDataset(datasetId: string, size: number): Promise<CaptchaSolution[]>;
|
|
108
108
|
getDappUserSolutionById(commitmentId: string): Promise<UserSolutionRecord | undefined>;
|
|
109
|
+
private static readonly DAPP_USER_COMMITMENT_PROJECTION;
|
|
109
110
|
getDappUserCommitmentById(commitmentId: string): Promise<UserCommitmentRecord | undefined>;
|
|
110
111
|
getDappUserCommitmentByAccount(userAccount: string, dappAccount: string): Promise<UserCommitmentRecord[]>;
|
|
111
112
|
approveDappUserCommitment(commitmentId: string, coords?: [number, number][][]): Promise<void>;
|
|
@@ -131,9 +132,7 @@ export declare class ProviderDatabase extends MongoDatabase implements IProvider
|
|
|
131
132
|
}) | undefined>;
|
|
132
133
|
removeDecisionMachineArtifact(id: string): Promise<boolean>;
|
|
133
134
|
removeAllDecisionMachineArtifacts(): Promise<number>;
|
|
134
|
-
setClientContextEntropy(account: string, contextType: ContextType, entropy: string): Promise<void>;
|
|
135
135
|
getClientContextEntropy(account: string, contextType: ContextType): Promise<string | undefined>;
|
|
136
|
-
sampleContextEntropy(sampleSize: number, siteKey: string, contextType: ContextType): Promise<string[]>;
|
|
137
136
|
getSpamEmailDomain(domain: string): Promise<SpamEmailDomainRecord | null>;
|
|
138
137
|
bulkUpdateSpamEmailDomains(domains: Array<{
|
|
139
138
|
filter: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/databases/provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACN,KAAK,eAAe,EAGpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,aAAa,EAGb,KAAK,kBAAkB,EACvB,WAAW,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/databases/provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACN,KAAK,eAAe,EAGpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,aAAa,EAGb,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAE1B,KAAK,uBAAuB,EAC5B,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAE/B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,OAAO,EACZ,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAGnB,KAAK,cAAc,EAGnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAIN,KAAK,YAAY,EAIjB,KAAK,iBAAiB,EAEtB,KAAK,gBAAgB,EAErB,KAAK,mBAAmB,EAGxB,KAAK,mBAAmB,EAKxB,KAAK,qBAAqB,EAE1B,KAAK,MAAM,EACX,KAAK,oBAAoB,EAEzB,KAAK,kBAAkB,EAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAStE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,aAAK,UAAU;IACd,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,YAAY,iBAAiB;IAC7B,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,eAAe,oBAAoB;IACnC,oBAAoB,yBAAyB;IAC7C,eAAe,oBAAoB;CACnC;AAsED,KAAK,uBAAuB,GAAG;IAC9B,KAAK,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,CAAC,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,gBACZ,SAAQ,aACR,YAAW,iBAAiB;IAShB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,MAAM,EAAS,MAAM,CAAC,UAAU,CAAC,CAAC;IAClC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,0BAA0B,CAAyB;IAC3D,OAAO,CAAC,sBAAsB,CAA4B;IAC1D,OAAO,CAAC,cAAc,CAAS;gBAEF,OAAO,EAAE,uBAAuB;IAc7D,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAIvD,oBAAoB,IAAI,OAAO;IAIhB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;cAQvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3C,UAAU;IAUV,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC;IAUxB,6BAA6B,IAAI,eAAe;IAUhD,kBAAkB,IAAI,eAAe;IAUtC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC7B,yBAAyB,IAAI,kBAAkB;IAYhD,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4GrE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAW1D,sBAAsB,CAC3B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAW3B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuDtD,gBAAgB,CACrB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,IAAI,EACf,IAAI,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC;IAkF3B,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC;IA6BnE,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB/D,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAenD,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAUrD,iBAAiB,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC;IA2BxD,6BAA6B,CAClC,QAAQ,EAAE,eAAe,EAAE,EAC3B,MAAM,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC;IA4DV,qBAAqB,CAC1B,SAAS,EAAE,cAAc,EACzB,UAAU,EAAE,sBAAsB,EAClC,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,kBAAkB,EAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,UAAQ,EACrB,aAAa,UAAQ,EACrB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IA2EV,8BAA8B,CACnC,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAsE7B,4BAA4B,CACjC,SAAS,EAAE,cAAc,EACzB,MAAM,EAAE,aAAa,EACrB,aAAa,UAAQ,EACrB,aAAa,UAAQ,EACrB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC;IAqFV,sBAAsB,CAC3B,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC;IAsBV,wBAAwB,CAC7B,SAAS,EAAE,cAAc,EACzB,UAAU,EAAE,sBAAsB,EAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,kBAAkB,EAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAsEV,iCAAiC,CACtC,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAkFhC,+BAA+B,CACpC,SAAS,EAAE,cAAc,EACzB,MAAM,EAAE,aAAa,EACrB,aAAa,UAAQ,EACrB,aAAa,UAAQ,EACrB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,EAC7B,oBAAoB,CAAC,EAAE,IAAI,GACzB,OAAO,CAAC,IAAI,CAAC;IAuFV,yBAAyB,CAC9B,SAAS,EAAE,cAAc,EACzB,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC;IAwCV,6BAA6B,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAqChE,8BAA8B,CACnC,KAAK,SAAO,EACZ,OAAO,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAwB5B,6BAA6B,CAClC,aAAa,EAAE,IAAI,EAAE,EACrB,aAAa,GAAE,IAAiB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAgBV,8BAA8B,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpE,wBAAwB,CAC7B,YAAY,EAAE,IAAI,EAClB,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC;IAgD3B,iCAAiC,CACtC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC;IAsBZ,iCAAiC,CACtC,KAAK,SAAO,EACZ,OAAO,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAyBxB,gCAAgC,CACrC,UAAU,EAAE,MAAM,EAAE,EACpB,aAAa,GAAE,IAAiB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAgBV,iCAAiC,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBtE,kBAAkB,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0DzD,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCnD,2BAA2B,CAChC,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IA0FzB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAUpE,qBAAqB,CAC1B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAmC/B,mBAAmB,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,eAAe,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,IAAI,CAAC;IAiDV,iCAAiC,CACtC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAC9C,KAAK,EAAE,iBAAiB,GACtB,OAAO,CAAC,IAAI,CAAC;IA+BV,oBAAoB,CACzB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,OAAO,CAAC;KACpB,EACD,kBAAkB,EAAE,IAAI,GACtB,OAAO,CAAC,OAAO,CAAC;IAqCb,6BAA6B,CAClC,iBAAiB,EAAE,MAAM,GACvB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAkCrC,yBAAyB,CACxB,KAAK,SAAO,EACZ,OAAO,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,EAAE,CAAC;IAyBrB,wBAAwB,CAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,aAAa,GAAE,IAAiB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAiBV,2BAA2B,CAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,IAAI,EACvB,oBAAoB,EAAE,IAAI,EAC1B,SAAS,EAAE,kBAAkB,EAC7B,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAoDV,yBAAyB,CAC9B,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,0BAA0B,CAAC;IA0ChC,kCAAkC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBtE,yBAAyB,CAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,aAAa,GACnB,OAAO,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC;IAqB3B,uBAAuB,CAC5B,SAAS,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,kBAAkB,EAAE,GAAG,SAAS,CAAC;IAqBtC,qCAAqC,CAC1C,kBAAkB,EAAE,MAAM,GACxB,OAAO,CAAC,MAAM,CAAC;IA8BZ,wCAAwC,CAC7C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACV,OAAO,CAAC,eAAe,EAAE,CAAC;IAyCvB,uBAAuB,CAC5B,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAsB1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,+BAA+B,CAiBE;IAMnD,yBAAyB,CAC9B,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAgBtC,8BAA8B,CACnC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAoB5B,yBAAyB,CAC9B,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC;IAoDV,4BAA4B,CACjC,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,YAAY,EACrB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC;IAwDV,8BAA8B,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBjE,gCAAgC,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBtE,sBAAsB,CAC3B,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,MAAM,EAAE,mBAAmB,GACzB,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAerC,0BAA0B,CAC/B,IAAI,EAAE,kBAAkB,EACxB,MAAM,CAAC,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAuBrC,yBAAyB,CAC9B,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,mBAAmB,GACzB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;IAcpB,yBAAyB,CAC9B,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,MAAM,EAAE,mBAAmB,EAC3B,MAAM,CAAC,EAAE,mBAAmB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAmBV,0BAA0B,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtE,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BjE,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYtD,mBAAmB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAQ9C,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IAqBnE,6BAA6B,CAClC,QAAQ,EAAE,uBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAwCV,0BAA0B,CAC/B,KAAK,EAAE,oBAAoB,EAC3B,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,mBAAmB,GACxB,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC;IAmBzC,8BAA8B,IAAI,OAAO,CAC9C,CAAC,uBAAuB,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAC7C;IAaK,8BAA8B,CACnC,EAAE,EAAE,MAAM,GACR,OAAO,CAAC,CAAC,uBAAuB,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;IAa7D,6BAA6B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAY3D,iCAAiC,IAAI,OAAO,CAAC,MAAM,CAAC;IAepD,uBAAuB,CAC5B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,WAAW,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IASxB,kBAAkB,CACvB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAqBlC,0BAA0B,CAC/B,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,MAAM,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,EAC1E,MAAM,EAAE,OAAO,GACb,OAAO,CAAC,IAAI,CAAC;CAmBhB"}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { MongoDatabase } from "../base/mongo.js";
|
|
2
2
|
import { ProsopoDBError } from "@prosopo/common";
|
|
3
|
-
import { CaptchaStates, CaptchaStatus, CaptchaType,
|
|
3
|
+
import { CaptchaStates, CaptchaStatus, CaptchaType, DatasetWithIdsAndTreeSchema, DecisionMachineKind, StoredStatusNames, UserCommitmentSchema, isBlockingCaptchaResult } from "@prosopo/types";
|
|
4
4
|
import { CaptchaRecordSchema, ClientContextEntropyRecordSchema, ClientRecordSchema, DatasetRecordSchema, DecisionMachineArtifactRecordSchema, PoWCaptchaRecordSchema, PuzzleCaptchaRecordSchema, ScheduledTaskRecordSchema, ScheduledTaskSchema, SessionRecordSchema, SolutionRecordSchema, SpamEmailDomainRecordSchema, UserCommitmentRecordSchema, UserSolutionRecordSchema } from "@prosopo/types-database";
|
|
5
5
|
import { isHex } from "@polkadot/util/is";
|
|
6
6
|
import { connectToRedis, setupRedisIndex } from "@prosopo/redis-client";
|
|
7
7
|
import { accessRulesRedisIndex, createRedisAccessRulesStorage } from "@prosopo/user-access-policy/redis";
|
|
8
8
|
import { assertCoordsSafe, buildDomainSuffixCandidates } from "@prosopo/util";
|
|
9
|
-
//#region src/databases/provider.ts
|
|
10
|
-
var TWENTY_FOUR_HOURS_IN_MS = 1440 * 60 * 1e3;
|
|
11
9
|
var MAX_DOMAIN_SUFFIX_CANDIDATES = 5;
|
|
12
10
|
var PROVIDER_TABLES = [
|
|
13
11
|
{
|
|
@@ -76,7 +74,7 @@ var PROVIDER_TABLES = [
|
|
|
76
74
|
schema: SpamEmailDomainRecordSchema
|
|
77
75
|
}
|
|
78
76
|
];
|
|
79
|
-
var ProviderDatabase = class extends MongoDatabase {
|
|
77
|
+
var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
80
78
|
constructor(options) {
|
|
81
79
|
super(options.mongo.url, options.mongo.dbname, options.mongo.authSource, options.logger);
|
|
82
80
|
this.options = options;
|
|
@@ -880,11 +878,20 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
880
878
|
* per page even with the right index; under a 1M-row pending backlog
|
|
881
879
|
* that hit multi-second query durations and thrashed the WT cache,
|
|
882
880
|
* dragging every co-tenant query with it.
|
|
881
|
+
*
|
|
882
|
+
* `.hint("pendingStage_partial")` pins the compound index against a
|
|
883
|
+
* planner regression seen in prod on 2026-08-21: on collections with
|
|
884
|
+
* both a plain `_id` index and the compound `{pendingStage:1, _id:1}`
|
|
885
|
+
* partial, the planner sometimes picks `_id` alone for
|
|
886
|
+
* `find({pendingStage:true}).sort({_id:1})` and scans the entire
|
|
887
|
+
* collection filtering in memory. Clearing the plan cache re-plans
|
|
888
|
+
* once but doesn't prevent the regression re-appearing after future
|
|
889
|
+
* catalog changes — the hint makes the choice explicit.
|
|
883
890
|
*/
|
|
884
891
|
async getUnstoredDappUserCommitments(limit = 1e3, afterId) {
|
|
885
892
|
const filter = { pendingStage: true };
|
|
886
893
|
if (afterId !== void 0) filter._id = { $gt: afterId };
|
|
887
|
-
return await this.tables?.commitment.find(filter).sort({ _id: 1 }).limit(limit).lean() || [];
|
|
894
|
+
return await this.tables?.commitment.find(filter).hint("pendingStage_partial").sort({ _id: 1 }).limit(limit).lean() || [];
|
|
888
895
|
}
|
|
889
896
|
/** @description Mark a list of captcha commits as stored.
|
|
890
897
|
*
|
|
@@ -970,7 +977,7 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
970
977
|
async getUnstoredDappUserPoWCommitments(limit = 1e3, afterId) {
|
|
971
978
|
const filter = { pendingStage: true };
|
|
972
979
|
if (afterId !== void 0) filter._id = { $gt: afterId };
|
|
973
|
-
return await this.tables?.powcaptcha.find(filter).sort({ _id: 1 }).limit(limit).lean() || [];
|
|
980
|
+
return await this.tables?.powcaptcha.find(filter).hint("pendingStage_partial").sort({ _id: 1 }).limit(limit).lean() || [];
|
|
974
981
|
}
|
|
975
982
|
/** @description Mark a list of PoW captcha commits as stored.
|
|
976
983
|
*
|
|
@@ -1299,7 +1306,7 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
1299
1306
|
getUnstoredSessionRecords(limit = 1e3, afterId) {
|
|
1300
1307
|
const filter = { pendingStage: true };
|
|
1301
1308
|
if (afterId !== void 0) filter._id = { $gt: afterId };
|
|
1302
|
-
return Promise.resolve(this.tables?.session).then((tbl) => tbl?.find(filter).sort({ _id: 1 }).limit(limit).lean()).then((docs) => docs || []);
|
|
1309
|
+
return Promise.resolve(this.tables?.session).then((tbl) => tbl?.find(filter).hint("pendingStage_partial").sort({ _id: 1 }).limit(limit).lean()).then((docs) => docs || []);
|
|
1303
1310
|
}
|
|
1304
1311
|
/** Mark a list of session records as stored.
|
|
1305
1312
|
*
|
|
@@ -1455,13 +1462,8 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
1455
1462
|
commitmentId
|
|
1456
1463
|
} });
|
|
1457
1464
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
* @param commitmentId
|
|
1461
|
-
*/
|
|
1462
|
-
async getDappUserCommitmentById(commitmentId) {
|
|
1463
|
-
const filter = { id: commitmentId };
|
|
1464
|
-
const doc = await this.tables?.commitment?.findOne(filter, {
|
|
1465
|
+
static {
|
|
1466
|
+
this.DAPP_USER_COMMITMENT_PROJECTION = {
|
|
1465
1467
|
id: 1,
|
|
1466
1468
|
result: 1,
|
|
1467
1469
|
serverChecked: 1,
|
|
@@ -1474,8 +1476,19 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
1474
1476
|
userAccount: 1,
|
|
1475
1477
|
dappAccount: 1,
|
|
1476
1478
|
headers: 1,
|
|
1477
|
-
ipInfo: 1
|
|
1478
|
-
|
|
1479
|
+
ipInfo: 1,
|
|
1480
|
+
behavioralDataPacked: 1,
|
|
1481
|
+
deviceCapability: 1,
|
|
1482
|
+
coords: 1
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* @description Get dapp user commitment by user account
|
|
1487
|
+
* @param commitmentId
|
|
1488
|
+
*/
|
|
1489
|
+
async getDappUserCommitmentById(commitmentId) {
|
|
1490
|
+
const filter = { id: commitmentId };
|
|
1491
|
+
const doc = await this.tables?.commitment?.findOne(filter, ProviderDatabase.DAPP_USER_COMMITMENT_PROJECTION).lean();
|
|
1479
1492
|
return doc ? doc : void 0;
|
|
1480
1493
|
}
|
|
1481
1494
|
/**
|
|
@@ -1488,10 +1501,7 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
1488
1501
|
userAccount,
|
|
1489
1502
|
dappAccount
|
|
1490
1503
|
};
|
|
1491
|
-
const docs = await this.tables?.commitment?.find(filter, {
|
|
1492
|
-
_id: 0,
|
|
1493
|
-
result: 1
|
|
1494
|
-
}, { sort: { _id: -1 } }).lean();
|
|
1504
|
+
const docs = await this.tables?.commitment?.find(filter, ProviderDatabase.DAPP_USER_COMMITMENT_PROJECTION, { sort: { _id: -1 } }).lean();
|
|
1495
1505
|
return docs ? docs : [];
|
|
1496
1506
|
}
|
|
1497
1507
|
/**
|
|
@@ -1771,21 +1781,14 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
1771
1781
|
return (await this.tables?.decisionMachine.deleteMany({}))?.deletedCount ?? 0;
|
|
1772
1782
|
}
|
|
1773
1783
|
/**
|
|
1774
|
-
* @description set client context-specific entropy
|
|
1775
|
-
*/
|
|
1776
|
-
async setClientContextEntropy(account, contextType, entropy) {
|
|
1777
|
-
const filter = {
|
|
1778
|
-
account,
|
|
1779
|
-
contextType
|
|
1780
|
-
};
|
|
1781
|
-
await this.tables?.clientContextEntropy.updateOne(filter, { $set: {
|
|
1782
|
-
account,
|
|
1783
|
-
contextType,
|
|
1784
|
-
entropy
|
|
1785
|
-
} }, { upsert: true });
|
|
1786
|
-
}
|
|
1787
|
-
/**
|
|
1788
1784
|
* @description get client context-specific entropy
|
|
1785
|
+
*
|
|
1786
|
+
* Read-only. The `clientcontextentropies` collection is populated
|
|
1787
|
+
* externally by the job-runner sweep — the provider used to compute
|
|
1788
|
+
* entropy locally via `sampleContextEntropy` + `setClientContextEntropy`
|
|
1789
|
+
* on a scheduled task, but that path was pulled 2026-08-21 (the sweep
|
|
1790
|
+
* aggregation was ~36 minutes of DB time per 6h, and the same
|
|
1791
|
+
* computation now runs off-provider across the full record set).
|
|
1789
1792
|
*/
|
|
1790
1793
|
async getClientContextEntropy(account, contextType) {
|
|
1791
1794
|
const filter = {
|
|
@@ -1795,43 +1798,6 @@ var ProviderDatabase = class extends MongoDatabase {
|
|
|
1795
1798
|
const doc = await this.tables?.clientContextEntropy.findOne(filter).lean();
|
|
1796
1799
|
return doc ? doc.entropy : void 0;
|
|
1797
1800
|
}
|
|
1798
|
-
/** Sample captcha records from the database for a specific context */
|
|
1799
|
-
async sampleContextEntropy(sampleSize, siteKey, contextType) {
|
|
1800
|
-
const size = sampleSize ? Math.abs(Math.trunc(sampleSize)) : 1;
|
|
1801
|
-
const max = 1e4;
|
|
1802
|
-
if (size > max) throw new ProsopoDBError("DATABASE.CAPTCHA_SAMPLE_SIZE_EXCEEDED", { context: {
|
|
1803
|
-
failedFuncName: this.sampleContextEntropy.name,
|
|
1804
|
-
sampleSize
|
|
1805
|
-
} });
|
|
1806
|
-
const pipeline = [
|
|
1807
|
-
{ $match: {
|
|
1808
|
-
dappAccount: siteKey,
|
|
1809
|
-
requestedAtTimestamp: { $gt: new Date((/* @__PURE__ */ new Date()).getTime() - TWENTY_FOUR_HOURS_IN_MS) }
|
|
1810
|
-
} },
|
|
1811
|
-
{ $sample: { size: max } },
|
|
1812
|
-
{ $lookup: {
|
|
1813
|
-
from: "sessions",
|
|
1814
|
-
localField: "sessionId",
|
|
1815
|
-
foreignField: "sessionId",
|
|
1816
|
-
as: "sessionData"
|
|
1817
|
-
} },
|
|
1818
|
-
{ $unwind: {
|
|
1819
|
-
path: "$sessionData",
|
|
1820
|
-
preserveNullAndEmptyArrays: false
|
|
1821
|
-
} }
|
|
1822
|
-
];
|
|
1823
|
-
if (contextType === ContextType.Webview) pipeline.push({ $match: { "sessionData.webView": true } });
|
|
1824
|
-
else if (contextType === ContextType.Default) pipeline.push({ $match: { "sessionData.webView": false } });
|
|
1825
|
-
pipeline.push({ $sample: { size } }, { $project: {
|
|
1826
|
-
_id: 0,
|
|
1827
|
-
sessionId: 1
|
|
1828
|
-
} });
|
|
1829
|
-
const docs = await this.tables?.powcaptcha.aggregate(pipeline);
|
|
1830
|
-
if (docs?.length === 0) return [];
|
|
1831
|
-
return (await Promise.all(docs.map(async (doc) => {
|
|
1832
|
-
if (doc.sessionId) return (await this.getSessionRecordBySessionId(doc.sessionId))?.decryptedHeadHash;
|
|
1833
|
-
}))).filter((headHash) => headHash !== void 0);
|
|
1834
|
-
}
|
|
1835
1801
|
async getSpamEmailDomain(domain) {
|
|
1836
1802
|
if (!this.tables?.spamEmailDomain) throw new ProsopoDBError("DATABASE.DATABASE_IMPORT_ERROR", { context: { failedFuncName: this.getSpamEmailDomain.name } });
|
|
1837
1803
|
const suffixCandidates = buildDomainSuffixCandidates(domain).slice(0, MAX_DOMAIN_SUFFIX_CANDIDATES);
|