@finsys/core 3.5.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -416,16 +416,34 @@ declare enum FileFieldTableType {
416
416
  * observedAt — ISO wall-clock of the extraction run
417
417
  * sourceRunId — the extraction run/job id that wrote it
418
418
  * origin — "extracted" (a real {value,confidence} leaf) vs "derived"
419
- * (computed / no-confidence path). A "derived" field must render
420
- * as "no confidence available", never a fabricated low score.
419
+ * (computed / no-confidence path) vs "manual" (SYS-2806, a
420
+ * lender-entered correction, committed once its edit overlay
421
+ * is approved). A "derived" field must render as "no
422
+ * confidence available", never a fabricated low score; a
423
+ * "manual" field must render as an edit indicator, not a
424
+ * confidence dot — confidence is always null for it too.
421
425
  */
426
+ /**
427
+ * Canonical origin values, single source of truth (Gemini-review finding:
428
+ * avoids duplicating the literal strings between the type and the runtime
429
+ * guard) -- mirrors the IhsStatus/IHS_VALID_STATUSES pattern in
430
+ * ihs-status.ts.
431
+ */
432
+ declare const IHS_FIELD_ORIGINS: readonly ["extracted", "derived", "manual"];
433
+ type IhsFieldOrigin = (typeof IHS_FIELD_ORIGINS)[number];
422
434
  interface IhsFieldProvenance {
423
435
  source: string;
424
436
  confidence: number | null;
425
437
  observedAt: string;
426
438
  sourceRunId: string | null;
427
- origin: 'extracted' | 'derived';
439
+ origin: IhsFieldOrigin;
428
440
  }
441
+ /**
442
+ * Type guard: narrows an unknown value to `IhsFieldOrigin` iff it is one of
443
+ * the three canonical origin strings. `origin` was previously validated
444
+ * only by the TS union — this is the first runtime check.
445
+ */
446
+ declare function isValidIhsFieldOrigin(origin: unknown): origin is IhsFieldOrigin;
429
447
  interface FileFieldTableItem {
430
448
  displayName: string;
431
449
  timePeriods: string[];
@@ -449,6 +467,22 @@ interface FileFieldTableData {
449
467
  items: FileFieldTableItem[];
450
468
  hasData: boolean;
451
469
  }
470
+ /**
471
+ * One sibling-table row as finsys-api's `docInstanceStorageService` writes
472
+ * it (SYS-2842) -- the unbounded counterpart to a T{n}-suffixed wide-table
473
+ * slot. `instanceKey` is the real, collision-free per-document key;
474
+ * `sourceLabel` is a human label when the doc type has one (e.g. a bank
475
+ * name); `timePeriod` is the same descriptive value column the legacy
476
+ * T{n} scheme used, kept for period-labeling and legacy provenance lookup
477
+ * (SYS-2886 Phase 5) -- no longer the row's key. Metric fields are the
478
+ * category's own base (unsuffixed) column names.
479
+ */
480
+ interface InstanceRow {
481
+ instanceKey: string;
482
+ sourceLabel?: string | null;
483
+ timePeriod?: string | null;
484
+ [metricKey: string]: unknown;
485
+ }
452
486
  /**
453
487
  * Per-document File metadata attached by finsys-api `getIhsDetailsById` as the
454
488
  * `documentMetadata` sibling map (SYS-2765), keyed by the document's raw stored
@@ -519,10 +553,42 @@ declare function getDisplayNames(): Record<string, string>;
519
553
  declare function getDisplayName(fieldName: string): string;
520
554
  declare function extractTimePeriods(columnNames: string[]): string[];
521
555
  declare function groupColumnsByTimePeriod(columnNames: string[]): Record<string, Record<string, string>>;
556
+ /**
557
+ * Groups fields by their catalog-declared document_group (falling back to
558
+ * the field's own name for anything untagged). Was a hardcoded, closed
559
+ * prefix-matching table (FIELD_GROUP_PREFIXES) requiring a code edit for
560
+ * every new document type; now reads the same document_group tag the
561
+ * catalog already carries for document-types.ts, so adding a document
562
+ * type is a catalog-only data change.
563
+ */
522
564
  declare function groupFieldsByPattern(fields: FieldData[]): Record<string, FieldData[]>;
523
- /** Returns human-friendly display names for field groups. */
524
565
  declare function getGroupDisplayNames(): Record<string, string>;
525
566
  declare function buildFileFieldTables(ihsData: Record<string, unknown>, fieldProvenance?: Record<string, IhsFieldProvenance>): Record<string, FileFieldTableData>;
567
+ /**
568
+ * Groups instance rows by base metric name -- the unbounded analog of
569
+ * groupColumnsByTimePeriod. `baseColumnNames` is the category's base
570
+ * (unsuffixed) field list; each returned group maps instance column
571
+ * label -> that metric's value on that row. Labels are disambiguated
572
+ * (see instanceColumnLabels) so two rows can never collide into the
573
+ * same key.
574
+ */
575
+ declare function groupColumnsByInstance(baseColumnNames: string[], instanceRows: InstanceRow[]): Record<string, Record<string, unknown>>;
576
+ /**
577
+ * Explicit base-column declaration for a category with NO catalog `file`
578
+ * spec -- e.g. invoice (SYS-2842 Phase 3), which was deliberately never
579
+ * registered in form-field-base-specs.json because getDocumentTypeGroups()
580
+ * is shared with resolveExtractionStatus, which assumes a category's wide-
581
+ * table columns exist to check "is this populated" against -- invoice has
582
+ * none (sibling-table only, no wideTableMirror). Registering it there would
583
+ * silently break resolveExtractionStatus's invoice status reporting. This
584
+ * override lets a category be instance-rendered without entering that
585
+ * shared registry at all.
586
+ */
587
+ interface CategorySpec {
588
+ displayName: string;
589
+ baseColumnNames: string[];
590
+ }
591
+ declare function buildFileFieldTablesFromInstances(instancesByCategory?: Record<string, InstanceRow[]>, fieldProvenance?: Record<string, IhsFieldProvenance>, categoryOverrides?: Record<string, CategorySpec>): Record<string, FileFieldTableData>;
526
592
  /** IHS doc-field key → human label (the fields that become document sections). */
527
593
  declare function getDocDisplayNames(): Record<string, string>;
528
594
  /** Doc types eligible for extraction (re-extract / view-JSON). */
@@ -583,19 +649,56 @@ declare enum ExtractionJobStatus {
583
649
  Failed = "failed"
584
650
  }
585
651
  /**
586
- * Document types that go through FinXtract extraction.
587
- * Values must match the `type` field on finsys-api File entity
588
- * and the config keys in finXtractApi.api.
652
+ * Document types that go through FinXtract extraction. Values must match
653
+ * the `type` field on finsys-api's File entity and the config keys in
654
+ * finXtractApi.api.
655
+ *
656
+ * Was a closed enum (FinancialStatement/BankStatement/Epf/Payslip/Ssm/
657
+ * Form9/Ic) requiring a core release to add a new document type, even
658
+ * though nothing outside finsys-api's own request validation actually
659
+ * needed it to be a closed set (confirmed: zero external consumers
660
+ * import a specific member by name). Now an open string, matching the
661
+ * AdapterCategory precedent (SYS-2500) -- the authoritative set of valid
662
+ * values lives in document-types.ts, derived from the field-spec catalog.
663
+ * Use isDocumentType()/assertDocumentType() from document-types.ts for
664
+ * the runtime validation that used to be the enum's job.
589
665
  */
590
- declare enum ExtractionFileType {
591
- FinancialStatement = "financialStatements",
592
- BankStatement = "bankStatements",
593
- Epf = "epfStatements",
594
- Payslip = "payslips",
595
- Ssm = "ssm",
596
- Form9 = "form9",
597
- Ic = "ic"
666
+ type ExtractionFileType = string;
667
+
668
+ type WireFormat = 'path_array' | 'url_string' | 'path_only';
669
+ type TimePeriodUnit = 'month' | 'year';
670
+ interface DocumentTypeGroup {
671
+ /** Wire/dispatch value, e.g. "bankStatements". */
672
+ readonly documentType: string;
673
+ /** Render/table grouping key, e.g. "ssm_documents". Distinct from documentType -- see module doc. */
674
+ readonly documentGroup: string;
675
+ /** Human-friendly label, e.g. "Bank Statements". */
676
+ readonly label: string;
677
+ /** Reserved for a future borrower-client payload-routing consolidation. Taken from the group's first entry; not enforced consistent across entries (all groups agree today, but a future mixed-format group would silently inherit the first entry's value). */
678
+ readonly wireFormat?: WireFormat;
679
+ /**
680
+ * The catalog's own `type: 'file'` entries belonging to this group, in
681
+ * catalog order. Each entry may carry its own document_slot/
682
+ * time_period_unit -- see TaggedFieldData and the module doc.
683
+ */
684
+ readonly fields: readonly TaggedFieldData[];
598
685
  }
686
+ interface TaggedFieldData extends FieldData {
687
+ document_type?: string;
688
+ document_group?: string;
689
+ document_group_label?: string;
690
+ wire_format?: WireFormat;
691
+ /** Which upload position this field represents (1st document, 2nd, etc). See module doc for why this is distinct from a "time period". */
692
+ document_slot?: number;
693
+ /** What unit document_slot's number measures for this field. */
694
+ time_period_unit?: TimePeriodUnit;
695
+ }
696
+ /** Every registered document type, in catalog declaration order. */
697
+ declare function getDocumentTypeGroups(): readonly DocumentTypeGroup[];
698
+ /** True if `id` is a registered document type (the wire/dispatch value). */
699
+ declare function isDocumentType(id: string): boolean;
700
+ /** Returns `id` if it's a registered document type, otherwise throws. */
701
+ declare function assertDocumentType(id: string): string;
599
702
 
600
703
  /**
601
704
  * IHS application status — canonical source of truth, mirroring finsys-api's
@@ -608,11 +711,19 @@ declare enum ExtractionFileType {
608
711
  * Lender rejection is not represented by a distinct status: when a lender
609
712
  * rejects an application, finsys-api transitions the record back to
610
713
  * `APPLICATION_FINALIZED` from `LENDER_EVALUATION`.
714
+ *
715
+ * `EditingApplication` (SYS-2806) is a lender-scoped detour off
716
+ * `LenderEvaluation` for manually editing extracted field values — not
717
+ * reachable from `ApplicationFinalized`. A lender toggles into it and back
718
+ * out to `LenderEvaluation`; it never appears on a record no lender has
719
+ * claimed. See finsys-api's `updateIhsStatusByLender` for the transition
720
+ * guard.
611
721
  */
612
722
  declare enum IhsStatus {
613
723
  CreatingApplication = "CREATING_APPLICATION",
614
724
  ApplicationFinalized = "APPLICATION_FINALIZED",
615
725
  LenderEvaluation = "LENDER_EVALUATION",
726
+ EditingApplication = "EDITING_APPLICATION",
616
727
  Approved = "APPROVED",
617
728
  LouDelivered = "LOU_DELIVERED",
618
729
  AwaitingDisbursement = "AWAITING_DISBURSEMENT",
@@ -1348,4 +1459,4 @@ interface FieldMapEntry {
1348
1459
  readonly transform?: "identity" | "pct_to_ratio01" | "to_boolean" | "to_integer";
1349
1460
  }
1350
1461
 
1351
- export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DropdownOption, type EditorValidator, ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceValue, type PageConfig, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TypescriptImplementation, type UnifiedFormConfig, type Validator, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, buildDocumentRows, buildFileFieldTables, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
1462
+ export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type CategorySpec, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DocumentTypeGroup, type DropdownOption, type EditorValidator, type ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_FIELD_ORIGINS, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldOrigin, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceRow, type InstanceValue, type PageConfig, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TaggedFieldData, type TimePeriodUnit, type TypescriptImplementation, type UnifiedFormConfig, type Validator, type WireFormat, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, assertDocumentType, buildDocumentRows, buildFileFieldTables, buildFileFieldTablesFromInstances, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getDocumentTypeGroups, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByInstance, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isDocumentType, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsFieldOrigin, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
package/dist/index.d.ts CHANGED
@@ -416,16 +416,34 @@ declare enum FileFieldTableType {
416
416
  * observedAt — ISO wall-clock of the extraction run
417
417
  * sourceRunId — the extraction run/job id that wrote it
418
418
  * origin — "extracted" (a real {value,confidence} leaf) vs "derived"
419
- * (computed / no-confidence path). A "derived" field must render
420
- * as "no confidence available", never a fabricated low score.
419
+ * (computed / no-confidence path) vs "manual" (SYS-2806, a
420
+ * lender-entered correction, committed once its edit overlay
421
+ * is approved). A "derived" field must render as "no
422
+ * confidence available", never a fabricated low score; a
423
+ * "manual" field must render as an edit indicator, not a
424
+ * confidence dot — confidence is always null for it too.
421
425
  */
426
+ /**
427
+ * Canonical origin values, single source of truth (Gemini-review finding:
428
+ * avoids duplicating the literal strings between the type and the runtime
429
+ * guard) -- mirrors the IhsStatus/IHS_VALID_STATUSES pattern in
430
+ * ihs-status.ts.
431
+ */
432
+ declare const IHS_FIELD_ORIGINS: readonly ["extracted", "derived", "manual"];
433
+ type IhsFieldOrigin = (typeof IHS_FIELD_ORIGINS)[number];
422
434
  interface IhsFieldProvenance {
423
435
  source: string;
424
436
  confidence: number | null;
425
437
  observedAt: string;
426
438
  sourceRunId: string | null;
427
- origin: 'extracted' | 'derived';
439
+ origin: IhsFieldOrigin;
428
440
  }
441
+ /**
442
+ * Type guard: narrows an unknown value to `IhsFieldOrigin` iff it is one of
443
+ * the three canonical origin strings. `origin` was previously validated
444
+ * only by the TS union — this is the first runtime check.
445
+ */
446
+ declare function isValidIhsFieldOrigin(origin: unknown): origin is IhsFieldOrigin;
429
447
  interface FileFieldTableItem {
430
448
  displayName: string;
431
449
  timePeriods: string[];
@@ -449,6 +467,22 @@ interface FileFieldTableData {
449
467
  items: FileFieldTableItem[];
450
468
  hasData: boolean;
451
469
  }
470
+ /**
471
+ * One sibling-table row as finsys-api's `docInstanceStorageService` writes
472
+ * it (SYS-2842) -- the unbounded counterpart to a T{n}-suffixed wide-table
473
+ * slot. `instanceKey` is the real, collision-free per-document key;
474
+ * `sourceLabel` is a human label when the doc type has one (e.g. a bank
475
+ * name); `timePeriod` is the same descriptive value column the legacy
476
+ * T{n} scheme used, kept for period-labeling and legacy provenance lookup
477
+ * (SYS-2886 Phase 5) -- no longer the row's key. Metric fields are the
478
+ * category's own base (unsuffixed) column names.
479
+ */
480
+ interface InstanceRow {
481
+ instanceKey: string;
482
+ sourceLabel?: string | null;
483
+ timePeriod?: string | null;
484
+ [metricKey: string]: unknown;
485
+ }
452
486
  /**
453
487
  * Per-document File metadata attached by finsys-api `getIhsDetailsById` as the
454
488
  * `documentMetadata` sibling map (SYS-2765), keyed by the document's raw stored
@@ -519,10 +553,42 @@ declare function getDisplayNames(): Record<string, string>;
519
553
  declare function getDisplayName(fieldName: string): string;
520
554
  declare function extractTimePeriods(columnNames: string[]): string[];
521
555
  declare function groupColumnsByTimePeriod(columnNames: string[]): Record<string, Record<string, string>>;
556
+ /**
557
+ * Groups fields by their catalog-declared document_group (falling back to
558
+ * the field's own name for anything untagged). Was a hardcoded, closed
559
+ * prefix-matching table (FIELD_GROUP_PREFIXES) requiring a code edit for
560
+ * every new document type; now reads the same document_group tag the
561
+ * catalog already carries for document-types.ts, so adding a document
562
+ * type is a catalog-only data change.
563
+ */
522
564
  declare function groupFieldsByPattern(fields: FieldData[]): Record<string, FieldData[]>;
523
- /** Returns human-friendly display names for field groups. */
524
565
  declare function getGroupDisplayNames(): Record<string, string>;
525
566
  declare function buildFileFieldTables(ihsData: Record<string, unknown>, fieldProvenance?: Record<string, IhsFieldProvenance>): Record<string, FileFieldTableData>;
567
+ /**
568
+ * Groups instance rows by base metric name -- the unbounded analog of
569
+ * groupColumnsByTimePeriod. `baseColumnNames` is the category's base
570
+ * (unsuffixed) field list; each returned group maps instance column
571
+ * label -> that metric's value on that row. Labels are disambiguated
572
+ * (see instanceColumnLabels) so two rows can never collide into the
573
+ * same key.
574
+ */
575
+ declare function groupColumnsByInstance(baseColumnNames: string[], instanceRows: InstanceRow[]): Record<string, Record<string, unknown>>;
576
+ /**
577
+ * Explicit base-column declaration for a category with NO catalog `file`
578
+ * spec -- e.g. invoice (SYS-2842 Phase 3), which was deliberately never
579
+ * registered in form-field-base-specs.json because getDocumentTypeGroups()
580
+ * is shared with resolveExtractionStatus, which assumes a category's wide-
581
+ * table columns exist to check "is this populated" against -- invoice has
582
+ * none (sibling-table only, no wideTableMirror). Registering it there would
583
+ * silently break resolveExtractionStatus's invoice status reporting. This
584
+ * override lets a category be instance-rendered without entering that
585
+ * shared registry at all.
586
+ */
587
+ interface CategorySpec {
588
+ displayName: string;
589
+ baseColumnNames: string[];
590
+ }
591
+ declare function buildFileFieldTablesFromInstances(instancesByCategory?: Record<string, InstanceRow[]>, fieldProvenance?: Record<string, IhsFieldProvenance>, categoryOverrides?: Record<string, CategorySpec>): Record<string, FileFieldTableData>;
526
592
  /** IHS doc-field key → human label (the fields that become document sections). */
527
593
  declare function getDocDisplayNames(): Record<string, string>;
528
594
  /** Doc types eligible for extraction (re-extract / view-JSON). */
@@ -583,19 +649,56 @@ declare enum ExtractionJobStatus {
583
649
  Failed = "failed"
584
650
  }
585
651
  /**
586
- * Document types that go through FinXtract extraction.
587
- * Values must match the `type` field on finsys-api File entity
588
- * and the config keys in finXtractApi.api.
652
+ * Document types that go through FinXtract extraction. Values must match
653
+ * the `type` field on finsys-api's File entity and the config keys in
654
+ * finXtractApi.api.
655
+ *
656
+ * Was a closed enum (FinancialStatement/BankStatement/Epf/Payslip/Ssm/
657
+ * Form9/Ic) requiring a core release to add a new document type, even
658
+ * though nothing outside finsys-api's own request validation actually
659
+ * needed it to be a closed set (confirmed: zero external consumers
660
+ * import a specific member by name). Now an open string, matching the
661
+ * AdapterCategory precedent (SYS-2500) -- the authoritative set of valid
662
+ * values lives in document-types.ts, derived from the field-spec catalog.
663
+ * Use isDocumentType()/assertDocumentType() from document-types.ts for
664
+ * the runtime validation that used to be the enum's job.
589
665
  */
590
- declare enum ExtractionFileType {
591
- FinancialStatement = "financialStatements",
592
- BankStatement = "bankStatements",
593
- Epf = "epfStatements",
594
- Payslip = "payslips",
595
- Ssm = "ssm",
596
- Form9 = "form9",
597
- Ic = "ic"
666
+ type ExtractionFileType = string;
667
+
668
+ type WireFormat = 'path_array' | 'url_string' | 'path_only';
669
+ type TimePeriodUnit = 'month' | 'year';
670
+ interface DocumentTypeGroup {
671
+ /** Wire/dispatch value, e.g. "bankStatements". */
672
+ readonly documentType: string;
673
+ /** Render/table grouping key, e.g. "ssm_documents". Distinct from documentType -- see module doc. */
674
+ readonly documentGroup: string;
675
+ /** Human-friendly label, e.g. "Bank Statements". */
676
+ readonly label: string;
677
+ /** Reserved for a future borrower-client payload-routing consolidation. Taken from the group's first entry; not enforced consistent across entries (all groups agree today, but a future mixed-format group would silently inherit the first entry's value). */
678
+ readonly wireFormat?: WireFormat;
679
+ /**
680
+ * The catalog's own `type: 'file'` entries belonging to this group, in
681
+ * catalog order. Each entry may carry its own document_slot/
682
+ * time_period_unit -- see TaggedFieldData and the module doc.
683
+ */
684
+ readonly fields: readonly TaggedFieldData[];
598
685
  }
686
+ interface TaggedFieldData extends FieldData {
687
+ document_type?: string;
688
+ document_group?: string;
689
+ document_group_label?: string;
690
+ wire_format?: WireFormat;
691
+ /** Which upload position this field represents (1st document, 2nd, etc). See module doc for why this is distinct from a "time period". */
692
+ document_slot?: number;
693
+ /** What unit document_slot's number measures for this field. */
694
+ time_period_unit?: TimePeriodUnit;
695
+ }
696
+ /** Every registered document type, in catalog declaration order. */
697
+ declare function getDocumentTypeGroups(): readonly DocumentTypeGroup[];
698
+ /** True if `id` is a registered document type (the wire/dispatch value). */
699
+ declare function isDocumentType(id: string): boolean;
700
+ /** Returns `id` if it's a registered document type, otherwise throws. */
701
+ declare function assertDocumentType(id: string): string;
599
702
 
600
703
  /**
601
704
  * IHS application status — canonical source of truth, mirroring finsys-api's
@@ -608,11 +711,19 @@ declare enum ExtractionFileType {
608
711
  * Lender rejection is not represented by a distinct status: when a lender
609
712
  * rejects an application, finsys-api transitions the record back to
610
713
  * `APPLICATION_FINALIZED` from `LENDER_EVALUATION`.
714
+ *
715
+ * `EditingApplication` (SYS-2806) is a lender-scoped detour off
716
+ * `LenderEvaluation` for manually editing extracted field values — not
717
+ * reachable from `ApplicationFinalized`. A lender toggles into it and back
718
+ * out to `LenderEvaluation`; it never appears on a record no lender has
719
+ * claimed. See finsys-api's `updateIhsStatusByLender` for the transition
720
+ * guard.
611
721
  */
612
722
  declare enum IhsStatus {
613
723
  CreatingApplication = "CREATING_APPLICATION",
614
724
  ApplicationFinalized = "APPLICATION_FINALIZED",
615
725
  LenderEvaluation = "LENDER_EVALUATION",
726
+ EditingApplication = "EDITING_APPLICATION",
616
727
  Approved = "APPROVED",
617
728
  LouDelivered = "LOU_DELIVERED",
618
729
  AwaitingDisbursement = "AWAITING_DISBURSEMENT",
@@ -1348,4 +1459,4 @@ interface FieldMapEntry {
1348
1459
  readonly transform?: "identity" | "pct_to_ratio01" | "to_boolean" | "to_integer";
1349
1460
  }
1350
1461
 
1351
- export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DropdownOption, type EditorValidator, ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceValue, type PageConfig, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TypescriptImplementation, type UnifiedFormConfig, type Validator, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, buildDocumentRows, buildFileFieldTables, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };
1462
+ export { ADAPTER_CATEGORY_IDS, ALL_AGGREGATION_OPS, type AdapterCategory, AdapterError, type AdapterErrorReason, type AdapterExtraction, type AdapterManifest, type AggregationOp, type ApplicantIdentity, BASE_FIELD_SPECS, BasicFormField, type CanonicalFieldName, type CanonicalFieldSpec, type CanonicalFieldValue, type CanonicalFieldValues, type Category, type CategorySchema, type CategorySpec, type Choice, DEFAULT_VALIDATOR_DEFINITIONS, type DeclarativeImplementation, type DocExtractionResult, DocExtractionStatus, type DocumentFileMetadata, type DocumentRow, type DocumentRowCapabilities, type DocumentTypeGroup, type DropdownOption, type EditorValidator, type ExtractionFileType, type ExtractionJobRecord, ExtractionJobStatus, type ExtractionStatusResult, FIELD_TYPE_DEFINITIONS, type FieldData, type FieldGroup, type FieldMapEntry, type FieldReference, FieldType, type FileFieldTableData, type FileFieldTableItem, FileFieldTableType, FileFormField, FormField, FormFieldCategory, type FormFieldInputType, type FormFieldType, type FormFieldTypeDefinitions, FormFieldValidator, FormSpec, type FormValidatorDefinitions, IHS_FAILURE_STATUSES, IHS_FIELD_ORIGINS, IHS_TERMINAL_STATUSES, IHS_VALID_STATUSES, type IhsDetailCategory, type IhsFieldDetail, type IhsFieldOrigin, type IhsFieldProvenance, IhsStatus, IhsValueFormat, type InstanceRow, type InstanceValue, type PageConfig, type RHFSchemaOutput, type RHFStep, type RawPayload, type ResolvedField, Role, type SourceAdapter, type SurveyElementJSON, type SurveyJSON, type SurveyPageJSON, type TaggedFieldData, type TimePeriodUnit, type TypescriptImplementation, type UnifiedFormConfig, type Validator, type WireFormat, allCategories, applyAggregation, applyDynamicTitles, assertAdapterCategory, assertDocumentType, buildDocumentRows, buildFileFieldTables, buildFileFieldTablesFromInstances, categoryFieldsOf, categoryForField, categorySchemaOf, evaluateExpression, extractTimePeriods, formatDocumentSize, formatDocumentType, formatDocumentUploaded, generateRHFSchema, generateSurveyJson, getBaseCategories, getBaseFieldNames, getBaseFieldSpecMap, getBaseFieldSpecs, getCategoryName, getDisplayName, getDisplayNames, getDocDisplayNames, getDocumentTypeGroups, getExtractableDocTypes, getGroupDisplayNames, getPastMonthLabel, getPastYearLabel, getReuploadableDocTypes, getStepDefaultValues, getStepSchema, groupColumnsByInstance, groupColumnsByTimePeriod, groupDetailsByCategory, groupFieldsByCategory, groupFieldsByPattern, isAdapterCategory, isDocumentType, isFailureIhsStatus, isTerminalIhsStatus, isValidIhsFieldOrigin, isValidIhsStatus, parseFileField, processIhsDetails, resolveExtractionStatus, resolvePageFields, validateFormConfig, validateFormSpec, validatePagesConfig };