@paniniapi/forensics 0.0.0-stage → 0.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/asn1.d.ts +74 -0
- package/dist/asn1.d.ts.map +1 -0
- package/dist/asn1.js +186 -0
- package/dist/asn1.js.map +1 -0
- package/dist/consistency.d.ts +29 -0
- package/dist/consistency.d.ts.map +1 -0
- package/dist/consistency.js +163 -0
- package/dist/consistency.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/pdf/content.d.ts +22 -0
- package/dist/pdf/content.d.ts.map +1 -0
- package/dist/pdf/content.js +91 -0
- package/dist/pdf/content.js.map +1 -0
- package/dist/pdf/signature.d.ts +40 -0
- package/dist/pdf/signature.d.ts.map +1 -0
- package/dist/pdf/signature.js +351 -0
- package/dist/pdf/signature.js.map +1 -0
- package/dist/pdf/structure.d.ts +31 -0
- package/dist/pdf/structure.d.ts.map +1 -0
- package/dist/pdf/structure.js +172 -0
- package/dist/pdf/structure.js.map +1 -0
- package/dist/report.d.ts +29 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +159 -0
- package/dist/report.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/package.json +38 -4
- package/README.md +0 -3
package/dist/report.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Kapil — Project Panini Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { type SignatureOptions } from './pdf/signature';
|
|
17
|
+
import type { IntegrityReport } from './types';
|
|
18
|
+
import type { ExtractOptions } from '@paniniapi/extract';
|
|
19
|
+
export interface InspectOptions extends SignatureOptions {
|
|
20
|
+
/** Passed through to extractStatement (formatsDir, credentials, …). */
|
|
21
|
+
readonly extract?: ExtractOptions;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Full integrity inspection: container forensics (PDF only), signature
|
|
25
|
+
* validation, then extraction + arithmetic consistency. Never throws —
|
|
26
|
+
* malformed input produces warning signals, not exceptions.
|
|
27
|
+
*/
|
|
28
|
+
export declare function inspectStatement(input: Uint8Array | string, opts?: InspectOptions): Promise<IntegrityReport>;
|
|
29
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,OAAO,KAAK,EAEV,eAAe,EAIhB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,uEAAuE;IACvE,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;CACnC;AAoED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,eAAe,CAAC,CAgD1B"}
|
package/dist/report.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 Kapil — Project Panini Contributors
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.inspectStatement = inspectStatement;
|
|
19
|
+
/**
|
|
20
|
+
* Document-integrity orchestrator — one call runs every applicable
|
|
21
|
+
* forensic layer and returns an explainable verdict.
|
|
22
|
+
*/
|
|
23
|
+
const extract_1 = require("@paniniapi/extract");
|
|
24
|
+
const consistency_1 = require("./consistency");
|
|
25
|
+
const content_1 = require("./pdf/content");
|
|
26
|
+
const signature_1 = require("./pdf/signature");
|
|
27
|
+
const structure_1 = require("./pdf/structure");
|
|
28
|
+
function rollup(signals, sigs) {
|
|
29
|
+
if (signals.some((s) => s.severity === 'critical'))
|
|
30
|
+
return 'tamper_evidence';
|
|
31
|
+
if (signals.some((s) => s.severity === 'warning'))
|
|
32
|
+
return 'warnings';
|
|
33
|
+
if (sigs.some((s) => s.present))
|
|
34
|
+
return 'clean';
|
|
35
|
+
return signals.length === 0 ? 'inconclusive' : 'clean';
|
|
36
|
+
}
|
|
37
|
+
function signalizeSignatures(checks) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const c of checks) {
|
|
40
|
+
if (c.digestValid === false) {
|
|
41
|
+
out.push({
|
|
42
|
+
ruleId: 'sig.digest_mismatch',
|
|
43
|
+
severity: 'critical',
|
|
44
|
+
message: 'signed-byte-range digest does not match — the signed content was altered',
|
|
45
|
+
evidence: `field ${c.fieldName ?? '?'} signer ${c.signer ?? '?'}`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (c.signatureValid === false) {
|
|
49
|
+
out.push({
|
|
50
|
+
ruleId: 'sig.invalid',
|
|
51
|
+
severity: 'critical',
|
|
52
|
+
message: 'embedded signature fails cryptographic verification',
|
|
53
|
+
evidence: `field ${c.fieldName ?? '?'} signer ${c.signer ?? '?'}`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (c.postSignBytes) {
|
|
57
|
+
out.push({
|
|
58
|
+
ruleId: 'sig.post_sign_append',
|
|
59
|
+
severity: 'warning',
|
|
60
|
+
message: 'bytes exist after the signed range — content was appended post-signature',
|
|
61
|
+
evidence: `field ${c.fieldName ?? '?'}`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (c.signatureValid === true && c.digestValid === true) {
|
|
65
|
+
out.push({
|
|
66
|
+
ruleId: 'sig.verified',
|
|
67
|
+
severity: 'info',
|
|
68
|
+
message: `signature by ${c.signer ?? 'unknown'} verifies — signed bytes are provably unaltered`,
|
|
69
|
+
evidence: c.chainTrusted === true ? 'chain trusted' : 'chain untrusted or not evaluated',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (c.chainTrusted === false) {
|
|
73
|
+
out.push({
|
|
74
|
+
ruleId: 'sig.chain_untrusted',
|
|
75
|
+
severity: 'warning',
|
|
76
|
+
message: 'signature is cryptographically valid but the signer chain does not reach a trust anchor',
|
|
77
|
+
evidence: `signer ${c.signer ?? '?'}`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
for (const e of c.errors) {
|
|
81
|
+
out.push({
|
|
82
|
+
ruleId: 'sig.check_error',
|
|
83
|
+
severity: 'warning',
|
|
84
|
+
message: `signature check incomplete: ${e}`,
|
|
85
|
+
evidence: `field ${c.fieldName ?? '?'}`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Full integrity inspection: container forensics (PDF only), signature
|
|
93
|
+
* validation, then extraction + arithmetic consistency. Never throws —
|
|
94
|
+
* malformed input produces warning signals, not exceptions.
|
|
95
|
+
*/
|
|
96
|
+
async function inspectStatement(input, opts = {}) {
|
|
97
|
+
const signals = [];
|
|
98
|
+
const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : input;
|
|
99
|
+
const format = (0, extract_1.sniffFormat)(bytes);
|
|
100
|
+
let signatures = [];
|
|
101
|
+
if (format === 'pdf') {
|
|
102
|
+
// extraction first so the statement period can inform structure checks
|
|
103
|
+
let statement = null;
|
|
104
|
+
try {
|
|
105
|
+
statement = await (0, extract_1.extractStatement)(bytes, opts.extract);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* handled below */
|
|
109
|
+
}
|
|
110
|
+
signals.push(...(0, structure_1.inspectPdfStructure)(bytes, {
|
|
111
|
+
statementPeriodEnd: statement?.metadata['statementTo'] ?? null,
|
|
112
|
+
}), ...(0, content_1.inspectPdfContent)(bytes));
|
|
113
|
+
signatures = (0, signature_1.verifyPdfSignatures)(bytes, opts.trustStore === undefined ? {} : { trustStore: opts.trustStore });
|
|
114
|
+
return finalize(format, signals, signatures, statement);
|
|
115
|
+
}
|
|
116
|
+
if (format !== 'unknown') {
|
|
117
|
+
signals.push({
|
|
118
|
+
ruleId: 'container.no_integrity_layer',
|
|
119
|
+
severity: 'info',
|
|
120
|
+
message: `${format} carries no tamper-evident container — integrity verdict rests on arithmetic consistency only`,
|
|
121
|
+
evidence: `format=${format}`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
let statement = null;
|
|
125
|
+
try {
|
|
126
|
+
statement = await (0, extract_1.extractStatement)(bytes, opts.extract);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
signals.push({
|
|
130
|
+
ruleId: 'container.unreadable',
|
|
131
|
+
severity: 'warning',
|
|
132
|
+
message: 'input could not be extracted for consistency checks',
|
|
133
|
+
evidence: `format=${format}`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return finalize(format, signals, signatures, statement);
|
|
137
|
+
}
|
|
138
|
+
function finalize(format, signals, sigs, statement) {
|
|
139
|
+
let consistency = null;
|
|
140
|
+
const all = [...signals];
|
|
141
|
+
if (statement !== null && statement.transactions.length > 0) {
|
|
142
|
+
const c = (0, consistency_1.checkConsistency)(statement);
|
|
143
|
+
consistency = c.check;
|
|
144
|
+
all.push(...c.signals);
|
|
145
|
+
}
|
|
146
|
+
all.push(...signalizeSignatures(sigs));
|
|
147
|
+
const critical = all.filter((s) => s.severity === 'critical').length;
|
|
148
|
+
const warningCount = all.filter((s) => s.severity === 'warning').length;
|
|
149
|
+
return {
|
|
150
|
+
verdict: rollup(all, sigs),
|
|
151
|
+
format,
|
|
152
|
+
signals: all,
|
|
153
|
+
signatures: sigs,
|
|
154
|
+
consistency,
|
|
155
|
+
critical,
|
|
156
|
+
warningCount,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Kapil — Project Panini Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/** Severity of a forensic signal — verdict rolls up to the worst seen. */
|
|
17
|
+
export type SignalSeverity = 'info' | 'warning' | 'critical';
|
|
18
|
+
/** One explainable integrity finding. `ruleId` is stable for alerting. */
|
|
19
|
+
export interface IntegritySignal {
|
|
20
|
+
readonly ruleId: string;
|
|
21
|
+
readonly severity: SignalSeverity;
|
|
22
|
+
readonly message: string;
|
|
23
|
+
/** Human-readable evidence: offsets, row indices, expected vs actual. */
|
|
24
|
+
readonly evidence: string;
|
|
25
|
+
}
|
|
26
|
+
/** Result of validating one embedded PDF signature. */
|
|
27
|
+
export interface SignatureCheck {
|
|
28
|
+
/** True when a signature field was found and processed. */
|
|
29
|
+
readonly present: boolean;
|
|
30
|
+
readonly fieldName: string | null;
|
|
31
|
+
readonly signer: string | null;
|
|
32
|
+
readonly signTime: string | null;
|
|
33
|
+
/** Byte-range digest matched the CMS messageDigest attribute. */
|
|
34
|
+
readonly digestValid: boolean | null;
|
|
35
|
+
/** RSA/ECDSA signature verified over signedAttrs. */
|
|
36
|
+
readonly signatureValid: boolean | null;
|
|
37
|
+
/** Chain reached a caller-supplied trust anchor; null = no store. */
|
|
38
|
+
readonly chainTrusted: boolean | null;
|
|
39
|
+
/** Content exists after the signed ByteRange (post-sign append). */
|
|
40
|
+
readonly postSignBytes: boolean;
|
|
41
|
+
readonly errors: readonly string[];
|
|
42
|
+
}
|
|
43
|
+
/** Arithmetic-consistency findings over an extracted statement. */
|
|
44
|
+
export interface ConsistencyCheck {
|
|
45
|
+
readonly balanceChainBreaks: number;
|
|
46
|
+
readonly openingMismatch: boolean | null;
|
|
47
|
+
readonly closingMismatch: boolean | null;
|
|
48
|
+
readonly sumMismatch: boolean | null;
|
|
49
|
+
readonly outOfPeriodRows: number;
|
|
50
|
+
readonly duplicateRows: number;
|
|
51
|
+
}
|
|
52
|
+
export type IntegrityVerdict = 'clean' | 'warnings' | 'tamper_evidence' | 'inconclusive';
|
|
53
|
+
/** Top-level document integrity verdict — explainable, never a score. */
|
|
54
|
+
export interface IntegrityReport {
|
|
55
|
+
readonly verdict: IntegrityVerdict;
|
|
56
|
+
readonly format: string;
|
|
57
|
+
readonly signals: readonly IntegritySignal[];
|
|
58
|
+
readonly signatures: readonly SignatureCheck[];
|
|
59
|
+
readonly consistency: ConsistencyCheck | null;
|
|
60
|
+
/** Counts by severity for quick gating. */
|
|
61
|
+
readonly critical: number;
|
|
62
|
+
readonly warningCount: number;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,0EAA0E;AAC1E,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAE7D,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iEAAiE;IACjE,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IACrC,qDAAqD;IACrD,QAAQ,CAAC,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,qEAAqE;IACrE,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IACtC,oEAAoE;IACpE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAEzF,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC9C,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 Kapil — Project Panini Contributors
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paniniapi/forensics",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Deterministic document-integrity forensics for bank statements — PDF structural signals, CMS/PKCS#7 signature validation, and arithmetic consistency checks. Zero runtime dependencies, fully client-side.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"author": "Kapil",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"trust"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@paniniapi/extract": "0.2.3"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -b",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/peopleofproduct/Panini.git",
|
|
26
|
+
"directory": "packages/forensics"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/peopleofproduct/Panini#readme",
|
|
29
|
+
"bugs": "https://github.com/peopleofproduct/Panini/issues",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"fintech",
|
|
32
|
+
"india",
|
|
33
|
+
"bank-statement",
|
|
34
|
+
"pdf",
|
|
35
|
+
"forensics",
|
|
36
|
+
"tamper-detection",
|
|
37
|
+
"document-integrity",
|
|
38
|
+
"lending"
|
|
39
|
+
]
|
|
40
|
+
}
|
package/README.md
DELETED