@finsys/core 3.1.0 → 3.3.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/data/adapter-categories.json +93 -0
- package/dist/index.cjs +112 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +112 -5
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
|
@@ -291,6 +291,99 @@
|
|
|
291
291
|
"description": "Cash Conversion Cycle (DSO + days-inventory-outstanding − DPO). Working-capital efficiency; negative values (collect before paying suppliers) are strongest, very high values indicate cash tied up in operations."
|
|
292
292
|
}
|
|
293
293
|
]
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"id": "geolocation",
|
|
297
|
+
"displayName": "Geolocation",
|
|
298
|
+
"description": "Hourly-granularity movement track plus derived mobility signals for an applicant, sourced from any location-capable provider (telco network location, mobile-SDK GPS, GIS / address-verification services). Two instance kinds share this category: point instances (instanceKey 'pt:<ISO-hour>') carry one observed position per hourly bucket, mirroring the bank-statement multi-instance pattern; a single summary instance (instanceKey 'summary') carries adapter-derived behaviour signals — most importantly work-pattern regularity (sustained weekday dwell at a stable work anchor corroborates income reliability), residential stability, vacation windows, and dwell in operator-flagged hotspot zones. Vendor-agnostic: the source classifies or the adapter infers place labels; no provider-specific semantics leak into the field set. Raw coordinates are sensitive personal data — product-plane persistence is gated on PDPA consent + CRA Act 710 s25 retention review.",
|
|
299
|
+
"canonicalTable": "ihs_alt_data_geolocation",
|
|
300
|
+
"fields": [
|
|
301
|
+
{
|
|
302
|
+
"name": "geoLatitude",
|
|
303
|
+
"type": "number",
|
|
304
|
+
"unit": "deg",
|
|
305
|
+
"range": [-90, 90],
|
|
306
|
+
"description": "Observed latitude for this hourly bucket (point instances only)."
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"name": "geoLongitude",
|
|
310
|
+
"type": "number",
|
|
311
|
+
"unit": "deg",
|
|
312
|
+
"range": [-180, 180],
|
|
313
|
+
"description": "Observed longitude for this hourly bucket (point instances only)."
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"name": "geoAccuracyM",
|
|
317
|
+
"type": "number",
|
|
318
|
+
"unit": "meters",
|
|
319
|
+
"range": [0, 100000],
|
|
320
|
+
"description": "Source-reported horizontal accuracy radius of the observation. Cell-tower fixes are typically hundreds of meters; GPS fixes tens."
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"name": "geoBucket",
|
|
324
|
+
"type": "string",
|
|
325
|
+
"description": "ISO-8601 hour bucket of the observation, e.g. '2026-06-01T08'. Redundant with the instance key (pt:<bucket>) so consumers can query without parsing keys."
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"name": "geoPlaceLabel",
|
|
329
|
+
"type": "string",
|
|
330
|
+
"description": "Classified place for the bucket: home | work | commute | leisure | travel | hotspot | other. Classified by the source or inferred by the adapter from anchor dwell."
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"name": "geoWorkAttendanceRatio30d",
|
|
334
|
+
"type": "number",
|
|
335
|
+
"unit": "ratio",
|
|
336
|
+
"range": [0, 1],
|
|
337
|
+
"description": "Fraction of the last 30 weekdays with >= 6 hours of dwell at the inferred work anchor. The income-reliability headline: regular full-time work patterns corroborate declared employment income (summary instance only)."
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"name": "geoWorkDailyHoursAvg30d",
|
|
341
|
+
"type": "number",
|
|
342
|
+
"unit": "hours",
|
|
343
|
+
"range": [0, 24],
|
|
344
|
+
"description": "Mean daily hours of work-anchor dwell across the last 30 weekdays (summary instance only)."
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"name": "geoLocationStabilityScore",
|
|
348
|
+
"type": "number",
|
|
349
|
+
"unit": "score",
|
|
350
|
+
"range": [0, 1],
|
|
351
|
+
"description": "Residential stability: share of nights spent at the primary home anchor over the observation window. 1 = every night at home (summary instance only)."
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"name": "geoCommuteRegularityRatio",
|
|
355
|
+
"type": "number",
|
|
356
|
+
"unit": "ratio",
|
|
357
|
+
"range": [0, 1],
|
|
358
|
+
"description": "Consistency of the weekday home->work->home rhythm: fraction of weekdays matching the dominant commute pattern within an hour's tolerance (summary instance only)."
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"name": "geoVacationDays90d",
|
|
362
|
+
"type": "number",
|
|
363
|
+
"unit": "days",
|
|
364
|
+
"range": [0, 90],
|
|
365
|
+
"description": "Days in the last 90 spent fully away from both home and work anchors (contiguous travel windows; summary instance only)."
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"name": "geoHotspotDwellRatio",
|
|
369
|
+
"type": "number",
|
|
370
|
+
"unit": "ratio",
|
|
371
|
+
"range": [0, 1],
|
|
372
|
+
"description": "Share of observed buckets spent inside operator-flagged hotspot zones (known fraud / illicit-activity locations supplied to the adapter). Non-zero values warrant review, not automatic decline (summary instance only)."
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"name": "geoPrimaryStateCode",
|
|
376
|
+
"type": "string",
|
|
377
|
+
"description": "Malaysian state / federal-territory code of the primary home anchor, e.g. PNG, KUL, JHR (summary instance only)."
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"name": "geoAddressMatchScore",
|
|
381
|
+
"type": "number",
|
|
382
|
+
"unit": "score",
|
|
383
|
+
"range": [0, 1],
|
|
384
|
+
"description": "Agreement between the inferred home anchor and the applicant's registered residential address. 1 = same premises, 0 = different state (summary instance only)."
|
|
385
|
+
}
|
|
386
|
+
]
|
|
294
387
|
}
|
|
295
388
|
]
|
|
296
389
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -9461,7 +9461,7 @@ function formatValue(value, numeric) {
|
|
|
9461
9461
|
}
|
|
9462
9462
|
return String(value);
|
|
9463
9463
|
}
|
|
9464
|
-
function buildTableForGroup(groupName, fields, ihsData) {
|
|
9464
|
+
function buildTableForGroup(groupName, fields, ihsData, fieldProvenance) {
|
|
9465
9465
|
const allColumns = [];
|
|
9466
9466
|
for (const field of fields) {
|
|
9467
9467
|
if (field.ihs_column_names) {
|
|
@@ -9480,11 +9480,20 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9480
9480
|
const numeric = isNumericField(baseName);
|
|
9481
9481
|
const data = {};
|
|
9482
9482
|
const formattedData = {};
|
|
9483
|
+
const confidence = {};
|
|
9484
|
+
const provenance = {};
|
|
9483
9485
|
for (const period of periods) {
|
|
9484
9486
|
const colName = periodMap[period];
|
|
9485
9487
|
const value = colName ? ihsData[colName] ?? null : null;
|
|
9486
9488
|
data[period] = value;
|
|
9487
9489
|
formattedData[period] = formatValue(value, numeric);
|
|
9490
|
+
const prov = colName ? fieldProvenance?.[colName] : void 0;
|
|
9491
|
+
if (prov) {
|
|
9492
|
+
provenance[period] = prov;
|
|
9493
|
+
if (prov.origin === "extracted" && typeof prov.confidence === "number" && !Number.isNaN(prov.confidence)) {
|
|
9494
|
+
confidence[period] = prov.confidence;
|
|
9495
|
+
}
|
|
9496
|
+
}
|
|
9488
9497
|
}
|
|
9489
9498
|
items.push({
|
|
9490
9499
|
displayName: getDisplayName(baseName),
|
|
@@ -9492,7 +9501,9 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9492
9501
|
data,
|
|
9493
9502
|
formattedData,
|
|
9494
9503
|
type: tableType,
|
|
9495
|
-
isNumeric: numeric
|
|
9504
|
+
isNumeric: numeric,
|
|
9505
|
+
...Object.keys(confidence).length ? { confidence } : {},
|
|
9506
|
+
...Object.keys(provenance).length ? { provenance } : {}
|
|
9496
9507
|
});
|
|
9497
9508
|
}
|
|
9498
9509
|
const hasData = items.some(
|
|
@@ -9504,13 +9515,16 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9504
9515
|
for (const colName of allColumns) {
|
|
9505
9516
|
const value = ihsData[colName] ?? null;
|
|
9506
9517
|
const numeric = isNumericField(colName);
|
|
9518
|
+
const prov = fieldProvenance?.[colName];
|
|
9507
9519
|
items.push({
|
|
9508
9520
|
displayName: getDisplayName(colName),
|
|
9509
9521
|
timePeriods: [],
|
|
9510
9522
|
data: { value },
|
|
9511
9523
|
formattedData: { value: formatValue(value, numeric) },
|
|
9512
9524
|
type: tableType,
|
|
9513
|
-
isNumeric: numeric
|
|
9525
|
+
isNumeric: numeric,
|
|
9526
|
+
...prov && prov.origin === "extracted" && typeof prov.confidence === "number" && !Number.isNaN(prov.confidence) ? { confidence: { value: prov.confidence } } : {},
|
|
9527
|
+
...prov ? { provenance: { value: prov } } : {}
|
|
9514
9528
|
});
|
|
9515
9529
|
}
|
|
9516
9530
|
const hasData = items.some((item) => {
|
|
@@ -9520,13 +9534,13 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9520
9534
|
return { name: groupName, displayName: groupDisplayName, type: tableType, items, hasData };
|
|
9521
9535
|
}
|
|
9522
9536
|
}
|
|
9523
|
-
function buildFileFieldTables(ihsData) {
|
|
9537
|
+
function buildFileFieldTables(ihsData, fieldProvenance) {
|
|
9524
9538
|
const specs = getBaseFieldSpecs();
|
|
9525
9539
|
const fileFields = specs.filter((f) => f.type === "file" && f.ihs_column_names?.length);
|
|
9526
9540
|
const grouped = groupFieldsByPattern(fileFields);
|
|
9527
9541
|
const tables = {};
|
|
9528
9542
|
for (const [groupName, fields] of Object.entries(grouped)) {
|
|
9529
|
-
const table = buildTableForGroup(groupName, fields, ihsData);
|
|
9543
|
+
const table = buildTableForGroup(groupName, fields, ihsData, fieldProvenance);
|
|
9530
9544
|
if (table && table.hasData) {
|
|
9531
9545
|
tables[groupName] = table;
|
|
9532
9546
|
}
|
|
@@ -10197,6 +10211,99 @@ var adapter_categories_default = {
|
|
|
10197
10211
|
description: "Cash Conversion Cycle (DSO + days-inventory-outstanding \u2212 DPO). Working-capital efficiency; negative values (collect before paying suppliers) are strongest, very high values indicate cash tied up in operations."
|
|
10198
10212
|
}
|
|
10199
10213
|
]
|
|
10214
|
+
},
|
|
10215
|
+
{
|
|
10216
|
+
id: "geolocation",
|
|
10217
|
+
displayName: "Geolocation",
|
|
10218
|
+
description: "Hourly-granularity movement track plus derived mobility signals for an applicant, sourced from any location-capable provider (telco network location, mobile-SDK GPS, GIS / address-verification services). Two instance kinds share this category: point instances (instanceKey 'pt:<ISO-hour>') carry one observed position per hourly bucket, mirroring the bank-statement multi-instance pattern; a single summary instance (instanceKey 'summary') carries adapter-derived behaviour signals \u2014 most importantly work-pattern regularity (sustained weekday dwell at a stable work anchor corroborates income reliability), residential stability, vacation windows, and dwell in operator-flagged hotspot zones. Vendor-agnostic: the source classifies or the adapter infers place labels; no provider-specific semantics leak into the field set. Raw coordinates are sensitive personal data \u2014 product-plane persistence is gated on PDPA consent + CRA Act 710 s25 retention review.",
|
|
10219
|
+
canonicalTable: "ihs_alt_data_geolocation",
|
|
10220
|
+
fields: [
|
|
10221
|
+
{
|
|
10222
|
+
name: "geoLatitude",
|
|
10223
|
+
type: "number",
|
|
10224
|
+
unit: "deg",
|
|
10225
|
+
range: [-90, 90],
|
|
10226
|
+
description: "Observed latitude for this hourly bucket (point instances only)."
|
|
10227
|
+
},
|
|
10228
|
+
{
|
|
10229
|
+
name: "geoLongitude",
|
|
10230
|
+
type: "number",
|
|
10231
|
+
unit: "deg",
|
|
10232
|
+
range: [-180, 180],
|
|
10233
|
+
description: "Observed longitude for this hourly bucket (point instances only)."
|
|
10234
|
+
},
|
|
10235
|
+
{
|
|
10236
|
+
name: "geoAccuracyM",
|
|
10237
|
+
type: "number",
|
|
10238
|
+
unit: "meters",
|
|
10239
|
+
range: [0, 1e5],
|
|
10240
|
+
description: "Source-reported horizontal accuracy radius of the observation. Cell-tower fixes are typically hundreds of meters; GPS fixes tens."
|
|
10241
|
+
},
|
|
10242
|
+
{
|
|
10243
|
+
name: "geoBucket",
|
|
10244
|
+
type: "string",
|
|
10245
|
+
description: "ISO-8601 hour bucket of the observation, e.g. '2026-06-01T08'. Redundant with the instance key (pt:<bucket>) so consumers can query without parsing keys."
|
|
10246
|
+
},
|
|
10247
|
+
{
|
|
10248
|
+
name: "geoPlaceLabel",
|
|
10249
|
+
type: "string",
|
|
10250
|
+
description: "Classified place for the bucket: home | work | commute | leisure | travel | hotspot | other. Classified by the source or inferred by the adapter from anchor dwell."
|
|
10251
|
+
},
|
|
10252
|
+
{
|
|
10253
|
+
name: "geoWorkAttendanceRatio30d",
|
|
10254
|
+
type: "number",
|
|
10255
|
+
unit: "ratio",
|
|
10256
|
+
range: [0, 1],
|
|
10257
|
+
description: "Fraction of the last 30 weekdays with >= 6 hours of dwell at the inferred work anchor. The income-reliability headline: regular full-time work patterns corroborate declared employment income (summary instance only)."
|
|
10258
|
+
},
|
|
10259
|
+
{
|
|
10260
|
+
name: "geoWorkDailyHoursAvg30d",
|
|
10261
|
+
type: "number",
|
|
10262
|
+
unit: "hours",
|
|
10263
|
+
range: [0, 24],
|
|
10264
|
+
description: "Mean daily hours of work-anchor dwell across the last 30 weekdays (summary instance only)."
|
|
10265
|
+
},
|
|
10266
|
+
{
|
|
10267
|
+
name: "geoLocationStabilityScore",
|
|
10268
|
+
type: "number",
|
|
10269
|
+
unit: "score",
|
|
10270
|
+
range: [0, 1],
|
|
10271
|
+
description: "Residential stability: share of nights spent at the primary home anchor over the observation window. 1 = every night at home (summary instance only)."
|
|
10272
|
+
},
|
|
10273
|
+
{
|
|
10274
|
+
name: "geoCommuteRegularityRatio",
|
|
10275
|
+
type: "number",
|
|
10276
|
+
unit: "ratio",
|
|
10277
|
+
range: [0, 1],
|
|
10278
|
+
description: "Consistency of the weekday home->work->home rhythm: fraction of weekdays matching the dominant commute pattern within an hour's tolerance (summary instance only)."
|
|
10279
|
+
},
|
|
10280
|
+
{
|
|
10281
|
+
name: "geoVacationDays90d",
|
|
10282
|
+
type: "number",
|
|
10283
|
+
unit: "days",
|
|
10284
|
+
range: [0, 90],
|
|
10285
|
+
description: "Days in the last 90 spent fully away from both home and work anchors (contiguous travel windows; summary instance only)."
|
|
10286
|
+
},
|
|
10287
|
+
{
|
|
10288
|
+
name: "geoHotspotDwellRatio",
|
|
10289
|
+
type: "number",
|
|
10290
|
+
unit: "ratio",
|
|
10291
|
+
range: [0, 1],
|
|
10292
|
+
description: "Share of observed buckets spent inside operator-flagged hotspot zones (known fraud / illicit-activity locations supplied to the adapter). Non-zero values warrant review, not automatic decline (summary instance only)."
|
|
10293
|
+
},
|
|
10294
|
+
{
|
|
10295
|
+
name: "geoPrimaryStateCode",
|
|
10296
|
+
type: "string",
|
|
10297
|
+
description: "Malaysian state / federal-territory code of the primary home anchor, e.g. PNG, KUL, JHR (summary instance only)."
|
|
10298
|
+
},
|
|
10299
|
+
{
|
|
10300
|
+
name: "geoAddressMatchScore",
|
|
10301
|
+
type: "number",
|
|
10302
|
+
unit: "score",
|
|
10303
|
+
range: [0, 1],
|
|
10304
|
+
description: "Agreement between the inferred home anchor and the applicant's registered residential address. 1 = same premises, 0 = different state (summary instance only)."
|
|
10305
|
+
}
|
|
10306
|
+
]
|
|
10200
10307
|
}
|
|
10201
10308
|
]
|
|
10202
10309
|
};
|