@bdking71/spsignature 1.0.5 → 1.2.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.
@@ -1,24 +1,131 @@
1
+ /**
2
+ * @file SecureAuditSignature.ts
3
+ *
4
+ * Provides a secure, auditable digital-signature workflow for SharePoint
5
+ * web parts. The module renders a modal dialog that supports:
6
+ *
7
+ * • Drawing a signature on an HTML canvas
8
+ * • Uploading a signature image (PNG / JPG, ≤ 5 MB)
9
+ * • Re-using a previously cached (LZW-compressed) signature from
10
+ * localStorage
11
+ * • Optional two-factor authentication via a 5-digit passcode
12
+ * dispatched through email or Microsoft Teams
13
+ *
14
+ * After the user signs, the module hashes the audit envelope
15
+ * (payload + signer + timestamp) with SHA-256 so that the record can
16
+ * later be verified without exposing the original payload.
17
+ *
18
+ * @module SecureAuditSignature
19
+ */
1
20
  import { WebPartContext } from "@microsoft/sp-webpart-base";
2
- import { DeliveryChannel } from "./VerificationService";
21
+ import { DeliveryChannel } from "./OtpService";
22
+ /**
23
+ * Describes everything the caller must (or may) supply when requesting a
24
+ * signed audit record.
25
+ */
3
26
  export interface SignerContext {
27
+ /** SharePoint list-item ID that the signature relates to. */
4
28
  itemID: number;
29
+ /** Display name or email of the person signing. */
5
30
  signer: string;
31
+ /** Arbitrary key/value data to include in the audit envelope. */
6
32
  payload: Record<string, unknown>;
33
+ /** SPFx web-part context – required for PnPjs / Graph calls. */
7
34
  spContext: WebPartContext;
35
+ /** How to deliver the two-factor passcode (`"email"` | `"teams"`). */
8
36
  channel?: DeliveryChannel;
37
+ /**
38
+ * Whether two-factor authentication is required.
39
+ * Defaults to `true` when omitted or set to `undefined`.
40
+ */
9
41
  requireTFA?: boolean;
10
42
  }
43
+ /**
44
+ * The record that is ultimately persisted to SharePoint after a
45
+ * successful signing ceremony.
46
+ */
11
47
  export interface SharePointAuditRecord {
48
+ /** SHA-256 hex digest of the canonical audit envelope. */
12
49
  signatureHash: string;
50
+ /** LZW-compressed data-URI of the signature image. */
13
51
  signatureData: string;
52
+ /** ISO-8601 timestamp captured at the moment of signing. */
14
53
  signatureTimestamp: string;
54
+ /** ID of the verification list-item (if two-factor was used). */
15
55
  verificationItemId: number;
16
56
  }
57
+ /**
58
+ * The canonical shape that is hashed to produce `signatureHash`.
59
+ * The payload keys are sorted alphabetically so that hash
60
+ * verification is order-independent.
61
+ */
17
62
  export interface AuditEnvelopeRecord {
18
63
  payload: Record<string, unknown>;
19
64
  signer: string;
20
65
  timestamp: string;
21
66
  }
67
+ /**
68
+ * Opens a full-screen modal dialog that walks the user through:
69
+ *
70
+ * 1. (Optional) Two-factor passcode verification
71
+ * 2. Providing a digital signature (cached / drawn / uploaded)
72
+ * 3. Generating a tamper-evident SHA-256 audit record
73
+ *
74
+ * The returned promise resolves with a `SharePointAuditRecord` on
75
+ * success or `undefined` if the user cancels.
76
+ *
77
+ * @param context - Signer metadata and SPFx context.
78
+ * @param modalTitle - Title shown in the modal header.
79
+ * @param warningMessage - Instructional HTML rendered above the
80
+ * signature area.
81
+ * @returns A promise that resolves to the audit record or `undefined`.
82
+ *
83
+ * @throws {Error} If `context.spContext` is falsy.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * const record = await promptAndGenerateSecureAudit({
88
+ * itemID: 42,
89
+ * signer: currentUser.email,
90
+ * payload: { amount: 1500, vendor: "Contoso" },
91
+ * spContext: this.context,
92
+ * channel: "email",
93
+ * requireTFA: true,
94
+ * });
95
+ * ```
96
+ */
22
97
  export declare function promptAndGenerateSecureAudit(context: SignerContext, modalTitle?: string, warningMessage?: string): Promise<SharePointAuditRecord | undefined>;
98
+ /**
99
+ * Decompresses an LZW-compressed signature string back into its
100
+ * original `data:image/…` data-URI for display in reports or
101
+ * print views.
102
+ *
103
+ * @param compressedSignatureData - The LZW-compressed string stored
104
+ * in SharePoint.
105
+ * @returns The original data-URI, or an empty string if
106
+ * decompression fails or the result is not an image
107
+ * data-URI.
108
+ */
23
109
  export declare function getReportableSignature(compressedSignatureData: string): string;
24
- export declare function verifySecureAuditRecord(payloadToVerify: Record<string, unknown>, signer: string, timestamp: string, compressedSignatureData: string, storedHash: string): Promise<boolean>;
110
+ /**
111
+ * Re-computes the SHA-256 hash of the audit envelope constructed from
112
+ * the supplied parameters and compares it to `storedHash`.
113
+ *
114
+ * This allows any consumer to independently verify that a signed
115
+ * record has not been tampered with, without needing access to the
116
+ * original signature image.
117
+ *
118
+ * **Note:** Only top-level payload keys are sorted. If your payload
119
+ * contains nested objects whose key order may vary, consider using a
120
+ * deep-sort utility before calling this function.
121
+ *
122
+ * @param payloadToVerify - The payload that was originally signed.
123
+ * @param signer - The signer identifier used at sign time.
124
+ * @param timestamp - The ISO-8601 timestamp captured at sign
125
+ * time.
126
+ * @param _compressedSignatureData - The compressed signature (unused by the
127
+ * hash, retained for API symmetry).
128
+ * @param storedHash - The SHA-256 hex digest to compare against.
129
+ * @returns `true` if the recomputed hash matches `storedHash`.
130
+ */
131
+ export declare function verifySecureAuditRecord(payloadToVerify: Record<string, unknown>, signer: string, timestamp: string, _compressedSignatureData: string, storedHash: string): Promise<boolean>;