@tindalabs/shield 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.
Files changed (118) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +357 -0
  3. package/dist/assess.d.ts +16 -0
  4. package/dist/assess.js +220 -0
  5. package/dist/config/default-extensions-config.json +103 -0
  6. package/dist/core/ContentProtector.d.ts +63 -0
  7. package/dist/core/ContentProtector.js +281 -0
  8. package/dist/core/index.d.ts +1 -0
  9. package/dist/core/index.js +2 -0
  10. package/dist/core/mediator/ContentProtectionMediator.d.ts +86 -0
  11. package/dist/core/mediator/ContentProtectionMediator.js +238 -0
  12. package/dist/core/mediator/eventDataTypes.d.ts +112 -0
  13. package/dist/core/mediator/eventDataTypes.js +23 -0
  14. package/dist/core/mediator/handlers/abstractEventHandler.d.ts +41 -0
  15. package/dist/core/mediator/handlers/abstractEventHandler.js +59 -0
  16. package/dist/core/mediator/handlers/devToolsEventHandler.d.ts +9 -0
  17. package/dist/core/mediator/handlers/devToolsEventHandler.js +95 -0
  18. package/dist/core/mediator/handlers/eventHandlerRegistry.d.ts +9 -0
  19. package/dist/core/mediator/handlers/eventHandlerRegistry.js +34 -0
  20. package/dist/core/mediator/handlers/extensionEventHandlers.d.ts +40 -0
  21. package/dist/core/mediator/handlers/extensionEventHandlers.js +140 -0
  22. package/dist/core/mediator/handlers/iFrameEventHandlers.d.ts +27 -0
  23. package/dist/core/mediator/handlers/iFrameEventHandlers.js +93 -0
  24. package/dist/core/mediator/handlers/screenShotEventHandlers.d.ts +34 -0
  25. package/dist/core/mediator/handlers/screenShotEventHandlers.js +111 -0
  26. package/dist/core/mediator/protection-event.d.ts +77 -0
  27. package/dist/core/mediator/protection-event.js +32 -0
  28. package/dist/core/mediator/types.d.ts +105 -0
  29. package/dist/core/mediator/types.js +1 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.js +7 -0
  32. package/dist/otel.d.ts +24 -0
  33. package/dist/otel.js +83 -0
  34. package/dist/policy.d.ts +98 -0
  35. package/dist/policy.js +97 -0
  36. package/dist/strategies/AbstractStrategy.d.ts +124 -0
  37. package/dist/strategies/AbstractStrategy.js +256 -0
  38. package/dist/strategies/ClipboardStrategy.d.ts +67 -0
  39. package/dist/strategies/ClipboardStrategy.js +291 -0
  40. package/dist/strategies/ContextMenuStrategy.d.ts +60 -0
  41. package/dist/strategies/ContextMenuStrategy.js +454 -0
  42. package/dist/strategies/DevToolsStrategy.d.ts +55 -0
  43. package/dist/strategies/DevToolsStrategy.js +314 -0
  44. package/dist/strategies/ExtensionStrategy.d.ts +66 -0
  45. package/dist/strategies/ExtensionStrategy.js +486 -0
  46. package/dist/strategies/IFrameStrategy.d.ts +49 -0
  47. package/dist/strategies/IFrameStrategy.js +255 -0
  48. package/dist/strategies/KeyboardStrategy.d.ts +35 -0
  49. package/dist/strategies/KeyboardStrategy.js +130 -0
  50. package/dist/strategies/PrintStrategy.d.ts +47 -0
  51. package/dist/strategies/PrintStrategy.js +201 -0
  52. package/dist/strategies/ScreenshotStrategy.d.ts +90 -0
  53. package/dist/strategies/ScreenshotStrategy.js +502 -0
  54. package/dist/strategies/SelectionStrategy.d.ts +49 -0
  55. package/dist/strategies/SelectionStrategy.js +216 -0
  56. package/dist/strategies/WatermarkStrategy.d.ts +56 -0
  57. package/dist/strategies/WatermarkStrategy.js +287 -0
  58. package/dist/strategies/index.d.ts +10 -0
  59. package/dist/strategies/index.js +11 -0
  60. package/dist/types/assessment.d.ts +62 -0
  61. package/dist/types/assessment.js +1 -0
  62. package/dist/types/index.d.ts +278 -0
  63. package/dist/types/index.js +17 -0
  64. package/dist/utils/DOMObserver.d.ts +68 -0
  65. package/dist/utils/DOMObserver.js +134 -0
  66. package/dist/utils/base/LoggableComponent.d.ts +44 -0
  67. package/dist/utils/base/LoggableComponent.js +56 -0
  68. package/dist/utils/detectors/AbstractDevToolsDetector.d.ts +98 -0
  69. package/dist/utils/detectors/AbstractDevToolsDetector.js +127 -0
  70. package/dist/utils/detectors/dateToStringDetector.d.ts +43 -0
  71. package/dist/utils/detectors/dateToStringDetector.js +96 -0
  72. package/dist/utils/detectors/debugLibDetector.d.ts +64 -0
  73. package/dist/utils/detectors/debugLibDetector.js +195 -0
  74. package/dist/utils/detectors/debuggerDetector.d.ts +51 -0
  75. package/dist/utils/detectors/debuggerDetector.js +211 -0
  76. package/dist/utils/detectors/defineGetterDetector.d.ts +48 -0
  77. package/dist/utils/detectors/defineGetterDetector.js +150 -0
  78. package/dist/utils/detectors/detectorInterface.d.ts +36 -0
  79. package/dist/utils/detectors/detectorInterface.js +1 -0
  80. package/dist/utils/detectors/devToolsDetectorManager.d.ts +88 -0
  81. package/dist/utils/detectors/devToolsDetectorManager.js +243 -0
  82. package/dist/utils/detectors/funcToStringDetector.d.ts +43 -0
  83. package/dist/utils/detectors/funcToStringDetector.js +90 -0
  84. package/dist/utils/detectors/regToStringDetector.d.ts +43 -0
  85. package/dist/utils/detectors/regToStringDetector.js +129 -0
  86. package/dist/utils/detectors/sizeDetector.d.ts +54 -0
  87. package/dist/utils/detectors/sizeDetector.js +134 -0
  88. package/dist/utils/detectors/timingDetector.d.ts +55 -0
  89. package/dist/utils/detectors/timingDetector.js +143 -0
  90. package/dist/utils/dom.d.ts +20 -0
  91. package/dist/utils/dom.js +83 -0
  92. package/dist/utils/environment.d.ts +29 -0
  93. package/dist/utils/environment.js +267 -0
  94. package/dist/utils/eventManager.d.ts +162 -0
  95. package/dist/utils/eventManager.js +548 -0
  96. package/dist/utils/index.d.ts +2 -0
  97. package/dist/utils/index.js +3 -0
  98. package/dist/utils/intervalManager.d.ts +91 -0
  99. package/dist/utils/intervalManager.js +221 -0
  100. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.d.ts +41 -0
  101. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.js +135 -0
  102. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.d.ts +18 -0
  103. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.js +195 -0
  104. package/dist/utils/logging/simple/Loggable.d.ts +33 -0
  105. package/dist/utils/logging/simple/Loggable.js +1 -0
  106. package/dist/utils/logging/simple/LoggingDelegate.d.ts +42 -0
  107. package/dist/utils/logging/simple/LoggingDelegate.js +53 -0
  108. package/dist/utils/logging/simple/SimpleLoggingService.d.ts +39 -0
  109. package/dist/utils/logging/simple/SimpleLoggingService.js +58 -0
  110. package/dist/utils/orientation.d.ts +15 -0
  111. package/dist/utils/orientation.js +32 -0
  112. package/dist/utils/protectedContentManager.d.ts +155 -0
  113. package/dist/utils/protectedContentManager.js +424 -0
  114. package/dist/utils/securityOverlayManager.d.ts +253 -0
  115. package/dist/utils/securityOverlayManager.js +786 -0
  116. package/dist/utils/timeoutManager.d.ts +50 -0
  117. package/dist/utils/timeoutManager.js +113 -0
  118. package/package.json +61 -0
@@ -0,0 +1,140 @@
1
+ import { ProtectionEventType } from "../protection-event";
2
+ import { isEventType } from "../eventDataTypes";
3
+ import { AbstractEventHandler } from "./abstractEventHandler";
4
+ /**
5
+ * Handler for browser extension detection events
6
+ */
7
+ export class BrowserExtensionEventHandler extends AbstractEventHandler {
8
+ /**
9
+ * Create a new BrowserExtensionEventHandler
10
+ * @param mediator The protection mediator
11
+ * @param debugMode Enable debug mode for troubleshooting
12
+ */
13
+ constructor(mediator, debugMode = false) {
14
+ super(mediator, "BrowserExtensionEventHandler", debugMode);
15
+ }
16
+ /**
17
+ * Initialize the handler and subscribe to events
18
+ */
19
+ initialize() {
20
+ this.subscribe(ProtectionEventType.EXTENSION_DETECTED, this.handleExtensionDetected.bind(this));
21
+ }
22
+ /**
23
+ * Handle extension detection
24
+ * @param event the ProtectionEvent
25
+ */
26
+ handleExtensionDetected(event) {
27
+ // Use type guard for type-safe access
28
+ if (!isEventType(event, ProtectionEventType.EXTENSION_DETECTED)) {
29
+ this.error("Received invalid event type");
30
+ return;
31
+ }
32
+ const { data } = event;
33
+ this.log(`Handling extension detection state change, name=${data.extension?.name || "unknown"}`);
34
+ if (data.extension) {
35
+ this.applyExtensionProtection(event);
36
+ this.log("Blocking interface due to extension detection");
37
+ }
38
+ else {
39
+ this.removeExtensionProtection(event);
40
+ this.log("Unlocking interface after extension removal");
41
+ }
42
+ }
43
+ /**
44
+ * Handle extension detection
45
+ * @param event the typed ExtensionDetectedEvent
46
+ */
47
+ applyExtensionProtection(event) {
48
+ const { data } = event;
49
+ if (data.hideContent) {
50
+ this.mediator.publish({
51
+ type: ProtectionEventType.CONTENT_HIDDEN,
52
+ source: this.COMPONENT_NAME,
53
+ timestamp: Date.now(),
54
+ data: {
55
+ strategyName: this.COMPONENT_NAME,
56
+ reason: "extension_detected",
57
+ targetElement: data.target,
58
+ options: {
59
+ title: data.overlayOptions?.title,
60
+ message: data.overlayOptions?.message,
61
+ secondaryMessage: `"${data.extension?.name}" triggered this warning`,
62
+ textColor: "black",
63
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
64
+ },
65
+ priority: 8,
66
+ },
67
+ });
68
+ }
69
+ if (data.showOverlay) {
70
+ const extensionConfig = data.extension;
71
+ const additionalContent = `
72
+ <p style="font-size: 18px; margin-top: 20px;">Detected: ${extensionConfig.name}</p>
73
+ <p style="font-size: 14px; margin-top: 10px;">Risk Level: ${extensionConfig.risk.toUpperCase()}</p>
74
+ <button id="extension-protection-close" style="margin-top: 20px; padding: 10px 20px; background-color: white; color: black; border: none; border-radius: 4px; cursor: pointer; pointer-events: auto;">
75
+ I've Disabled the Extension
76
+ </button>
77
+ `;
78
+ setTimeout(() => {
79
+ const closeButton = document.getElementById("extension-protection-close");
80
+ if (closeButton) {
81
+ closeButton.addEventListener("click", () => {
82
+ window.location.reload();
83
+ });
84
+ }
85
+ }, 0);
86
+ this.mediator.publish({
87
+ type: ProtectionEventType.OVERLAY_SHOWN,
88
+ source: this.COMPONENT_NAME,
89
+ timestamp: Date.now(),
90
+ data: {
91
+ strategyName: this.COMPONENT_NAME,
92
+ overlayType: "extension",
93
+ options: {
94
+ ...data.overlayOptions,
95
+ blockEvents: true,
96
+ autoRestore: true,
97
+ additionalContent,
98
+ },
99
+ priority: 8,
100
+ },
101
+ });
102
+ }
103
+ }
104
+ /**
105
+ * Remove extension protection
106
+ * @param event The typed ExtensionDetectedEvent
107
+ */
108
+ removeExtensionProtection(event) {
109
+ const { data } = event;
110
+ if (data.hideContent) {
111
+ this.mediator.publish({
112
+ type: ProtectionEventType.CONTENT_RESTORED,
113
+ source: this.COMPONENT_NAME,
114
+ timestamp: Date.now(),
115
+ data: {
116
+ strategyName: this.COMPONENT_NAME,
117
+ targetElement: data.target,
118
+ },
119
+ });
120
+ }
121
+ if (data.showOverlay) {
122
+ this.mediator.publish({
123
+ type: ProtectionEventType.OVERLAY_REMOVED,
124
+ source: this.COMPONENT_NAME,
125
+ timestamp: Date.now(),
126
+ data: {
127
+ strategyName: this.COMPONENT_NAME,
128
+ overlayType: "extension",
129
+ reason: "extension_removed",
130
+ },
131
+ });
132
+ }
133
+ }
134
+ /**
135
+ * Additional cleanup to be performed on disposal
136
+ */
137
+ onDispose() {
138
+ // No additional cleanup needed for this handler
139
+ }
140
+ }
@@ -0,0 +1,27 @@
1
+ import type { ProtectionMediator } from "../../mediator/types";
2
+ import { type ProtectionEvent } from "../../mediator/protection-event";
3
+ import { AbstractEventHandler } from "./abstractEventHandler";
4
+ /**
5
+ * Handler for frame embedding events
6
+ */
7
+ export declare class FrameEmbeddingEventHandler extends AbstractEventHandler {
8
+ /**
9
+ * Create a new FrameEmbeddingEventHandler
10
+ * @param mediator The protection mediator
11
+ * @param debugMode Enable debug mode for troubleshooting
12
+ */
13
+ constructor(mediator: ProtectionMediator, debugMode?: boolean);
14
+ /**
15
+ * Initialize the handler and set up event subscriptions
16
+ */
17
+ protected initialize(): void;
18
+ /**
19
+ * Handle frame embedding detection event
20
+ * @param event The protection event containing frame embedding data
21
+ */
22
+ handleFrameEmbeddingDetected(event: ProtectionEvent): void;
23
+ /**
24
+ * Clean up resources when the handler is disposed
25
+ */
26
+ protected onDispose(): void;
27
+ }
@@ -0,0 +1,93 @@
1
+ import { ProtectionEventType } from "../../mediator/protection-event";
2
+ import { AbstractEventHandler } from "./abstractEventHandler";
3
+ /**
4
+ * Handler for frame embedding events
5
+ */
6
+ export class FrameEmbeddingEventHandler extends AbstractEventHandler {
7
+ /**
8
+ * Create a new FrameEmbeddingEventHandler
9
+ * @param mediator The protection mediator
10
+ * @param debugMode Enable debug mode for troubleshooting
11
+ */
12
+ constructor(mediator, debugMode = false) {
13
+ super(mediator, "FrameEmbeddingEventHandler", debugMode);
14
+ }
15
+ /**
16
+ * Initialize the handler and set up event subscriptions
17
+ */
18
+ initialize() {
19
+ // Subscribe to the FRAME_EMBEDDING_DETECTED event
20
+ this.subscribe(ProtectionEventType.FRAME_EMBEDDING_DETECTED, this.handleFrameEmbeddingDetected.bind(this));
21
+ this.log("Initialized and subscribed to frame embedding events");
22
+ }
23
+ /**
24
+ * Handle frame embedding detection event
25
+ * @param event The protection event containing frame embedding data
26
+ */
27
+ handleFrameEmbeddingDetected(event) {
28
+ try {
29
+ const frameEvent = event;
30
+ this.log("Handling frame embedding detected event", frameEvent);
31
+ const data = frameEvent.data;
32
+ if (!data) {
33
+ this.warn("Received invalid frame embedding event data");
34
+ return;
35
+ }
36
+ // Only handle external frames
37
+ if (data.isEmbedded && data.isExternalFrame) {
38
+ this.log(`Applying protection for external frame embedding from ${data.parentDomain || "unknown domain"}`);
39
+ // Show overlay if configured
40
+ if (data.showOverlay) {
41
+ this.mediator.publish({
42
+ type: ProtectionEventType.OVERLAY_SHOWN,
43
+ source: this.COMPONENT_NAME,
44
+ timestamp: Date.now(),
45
+ data: {
46
+ strategyName: this.COMPONENT_NAME,
47
+ overlayType: "frame_embedding",
48
+ options: {
49
+ ...data.overlayOptions,
50
+ blockEvents: true,
51
+ autoRestore: true,
52
+ },
53
+ priority: 9, // High priority for frame embedding
54
+ },
55
+ });
56
+ }
57
+ // Hide content if configured
58
+ if (data.hideContent) {
59
+ this.mediator.publish({
60
+ type: ProtectionEventType.CONTENT_HIDDEN,
61
+ source: this.COMPONENT_NAME,
62
+ timestamp: Date.now(),
63
+ data: {
64
+ strategyName: this.COMPONENT_NAME,
65
+ reason: "frame_embedding",
66
+ targetElement: data.targetElement,
67
+ options: {
68
+ title: data.overlayOptions?.title,
69
+ message: data.overlayOptions?.message,
70
+ secondaryMessage: data.overlayOptions?.secondaryMessage,
71
+ textColor: "black",
72
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
73
+ },
74
+ priority: 9, // High priority for frame embedding
75
+ },
76
+ });
77
+ }
78
+ }
79
+ else {
80
+ this.log("Skipping protection for non-external frame embedding");
81
+ }
82
+ }
83
+ catch (error) {
84
+ this.error("Error handling frame embedding detected event:", error);
85
+ }
86
+ }
87
+ /**
88
+ * Clean up resources when the handler is disposed
89
+ */
90
+ onDispose() {
91
+ // No additional cleanup needed beyond what the base class does
92
+ }
93
+ }
@@ -0,0 +1,34 @@
1
+ import type { ProtectionMediator } from "../../mediator/types";
2
+ import { type ProtectionEvent } from "../protection-event";
3
+ import { AbstractEventHandler } from "./abstractEventHandler";
4
+ /**
5
+ * Handler for screenshot detection events
6
+ */
7
+ export declare class ScreenshotEventHandler extends AbstractEventHandler {
8
+ private timeoutManager;
9
+ private activeTimeouts;
10
+ /**
11
+ * Create a new ScreenshotEventHandler
12
+ * @param mediator The protection mediator
13
+ * @param debugMode Enable debug mode for troubleshooting
14
+ */
15
+ constructor(mediator: ProtectionMediator, debugMode?: boolean);
16
+ /**
17
+ * Initialize the handler and subscribe to events
18
+ */
19
+ protected initialize(): void;
20
+ /**
21
+ * Handle screenshot attempt event
22
+ * @param event The protection event
23
+ */
24
+ handleScreenshotAttempt(event: ProtectionEvent): void;
25
+ /**
26
+ * Set debug mode
27
+ * @param enabled Whether debug mode should be enabled
28
+ */
29
+ setDebugMode(enabled: boolean): void;
30
+ /**
31
+ * Additional cleanup to be performed on disposal
32
+ */
33
+ protected onDispose(): void;
34
+ }
@@ -0,0 +1,111 @@
1
+ import { ProtectionEventType } from "../protection-event";
2
+ import { TimeoutManager } from "../../../utils/timeoutManager";
3
+ import { AbstractEventHandler } from "./abstractEventHandler";
4
+ /**
5
+ * Handler for screenshot detection events
6
+ */
7
+ export class ScreenshotEventHandler extends AbstractEventHandler {
8
+ /**
9
+ * Create a new ScreenshotEventHandler
10
+ * @param mediator The protection mediator
11
+ * @param debugMode Enable debug mode for troubleshooting
12
+ */
13
+ constructor(mediator, debugMode = false) {
14
+ super(mediator, "ScreenshotEventHandler", debugMode);
15
+ this.activeTimeouts = new Set(); // Track active timeouts
16
+ this.timeoutManager = TimeoutManager.getInstance();
17
+ this.timeoutManager.setDebugMode(this.debugMode);
18
+ }
19
+ /**
20
+ * Initialize the handler and subscribe to events
21
+ */
22
+ initialize() {
23
+ // Subscribe to the SCREENSHOT_ATTEMPT event
24
+ this.subscribe(ProtectionEventType.SCREENSHOT_ATTEMPT, this.handleScreenshotAttempt.bind(this));
25
+ }
26
+ /**
27
+ * Handle screenshot attempt event
28
+ * @param event The protection event
29
+ */
30
+ handleScreenshotAttempt(event) {
31
+ const screenshotEvent = event;
32
+ this.log("Handling screenshot attempt event", screenshotEvent);
33
+ // Generate a unique ID for this protection instance
34
+ const protectionId = `screenshot_${Date.now()}`;
35
+ if (screenshotEvent.data.showOverlay) {
36
+ this.mediator.publish({
37
+ type: ProtectionEventType.OVERLAY_SHOWN,
38
+ source: screenshotEvent.source,
39
+ timestamp: Date.now(),
40
+ data: {
41
+ strategyName: screenshotEvent.source,
42
+ overlayType: "screenshot",
43
+ options: {
44
+ ...screenshotEvent.data.overlayOptions,
45
+ blockEvents: false, // Don't block events, just show a notification
46
+ autoRestore: true,
47
+ },
48
+ priority: screenshotEvent.data.priority || 5,
49
+ duration: screenshotEvent.data.overlayOptions?.duration || 3000
50
+ },
51
+ });
52
+ }
53
+ if (screenshotEvent.data.hideContent) {
54
+ this.mediator.publish({
55
+ type: ProtectionEventType.CONTENT_HIDDEN,
56
+ source: screenshotEvent.source,
57
+ timestamp: Date.now(),
58
+ data: {
59
+ strategyName: screenshotEvent.source,
60
+ reason: "screenshot_attempt",
61
+ options: {
62
+ title: screenshotEvent.data.overlayOptions?.title,
63
+ message: screenshotEvent.data.overlayOptions?.message,
64
+ secondaryMessage: screenshotEvent.data.overlayOptions?.secondaryMessage,
65
+ textColor: 'black',
66
+ backgroundColor: screenshotEvent.data.overlayOptions?.backgroundColor || "rgba(0, 0, 0, 0.05)",
67
+ },
68
+ targetElement: screenshotEvent.data.target,
69
+ priority: screenshotEvent.data.priority || 5,
70
+ },
71
+ });
72
+ // Create a unique timeout ID for this screenshot event
73
+ const contentTimeoutId = `${protectionId}_content`;
74
+ this.activeTimeouts.add(contentTimeoutId);
75
+ // If duration is specified, set a timeout to restore content
76
+ if (screenshotEvent.data.overlayOptions?.duration) {
77
+ this.timeoutManager.setTimeout(contentTimeoutId, () => {
78
+ this.mediator.publish({
79
+ type: ProtectionEventType.CONTENT_RESTORED,
80
+ source: screenshotEvent.source,
81
+ timestamp: Date.now(),
82
+ data: {
83
+ strategyName: screenshotEvent.source,
84
+ targetElement: screenshotEvent.data.target,
85
+ },
86
+ });
87
+ this.activeTimeouts.delete(contentTimeoutId);
88
+ }, screenshotEvent.data.overlayOptions?.duration);
89
+ this.log(`Set timeout ${contentTimeoutId} to restore content after ${screenshotEvent.data.overlayOptions.duration}s`);
90
+ }
91
+ }
92
+ }
93
+ /**
94
+ * Set debug mode
95
+ * @param enabled Whether debug mode should be enabled
96
+ */
97
+ setDebugMode(enabled) {
98
+ super.setDebugMode(enabled);
99
+ this.timeoutManager.setDebugMode(enabled);
100
+ }
101
+ /**
102
+ * Additional cleanup to be performed on disposal
103
+ */
104
+ onDispose() {
105
+ // Clear all active timeouts
106
+ for (const timeoutId of this.activeTimeouts) {
107
+ this.timeoutManager.clearTimeout(timeoutId);
108
+ }
109
+ this.activeTimeouts.clear();
110
+ }
111
+ }
@@ -0,0 +1,77 @@
1
+ import { EventDataMap } from "./eventDataTypes";
2
+ /**
3
+ * Types of protection events that can be published and subscribed to.
4
+ *
5
+ * Only the events listed below are actually wired through the mediator today.
6
+ * The mediator pattern serves a specific case: a detect-and-react fan-out where
7
+ * one detection signal needs to coordinate multiple visible reactions (overlay,
8
+ * content hiding, telemetry). That's why only 4 of the 10 strategies use it —
9
+ * DevTools, Extension, IFrame, and Screenshot. The other 6 (Clipboard,
10
+ * Selection, ContextMenu, Keyboard, Print, Watermark) are direct-blocking
11
+ * strategies where the handler IS the strategy; routing them through the
12
+ * mediator would add ceremony for no decoupling benefit.
13
+ *
14
+ * If you need a NEW event type, add it here AND give it a `[NewType]: { ... }`
15
+ * entry in {@link EventDataMap}.
16
+ */
17
+ export declare enum ProtectionEventType {
18
+ STRATEGY_REMOVED = "strategy:removed",
19
+ DEVTOOLS_STATE_CHANGE = "protection:devtools",
20
+ EXTENSION_DETECTED = "protection:extension",
21
+ FRAME_EMBEDDING_DETECTED = "protection:frame",
22
+ SCREENSHOT_ATTEMPT = "protection:screenshot",
23
+ OVERLAY_SHOWN = "overlay:shown",
24
+ OVERLAY_REMOVED = "overlay:removed",
25
+ OVERLAY_RESTORED = "overlay:restored",
26
+ CONTENT_HIDDEN = "content:hidden",
27
+ CONTENT_RESTORED = "content:restored"
28
+ }
29
+ /**
30
+ * Base protection event interface
31
+ */
32
+ export interface ProtectionEvent {
33
+ /**
34
+ * Type of the event
35
+ */
36
+ type: ProtectionEventType;
37
+ /**
38
+ * Source of the event (usually strategy name)
39
+ */
40
+ source: string;
41
+ /**
42
+ * Timestamp when the event occurred
43
+ */
44
+ timestamp: number;
45
+ /**
46
+ * Additional data specific to the event type
47
+ */
48
+ data?: unknown;
49
+ }
50
+ /**
51
+ * Event for DevTools state changes
52
+ */
53
+ export interface DevToolsEvent extends ProtectionEvent {
54
+ type: ProtectionEventType.DEVTOOLS_STATE_CHANGE;
55
+ data: EventDataMap[ProtectionEventType.DEVTOOLS_STATE_CHANGE];
56
+ }
57
+ /**
58
+ * Event for extension detection
59
+ */
60
+ export interface ExtensionEvent extends ProtectionEvent {
61
+ type: ProtectionEventType.EXTENSION_DETECTED;
62
+ data: EventDataMap[ProtectionEventType.EXTENSION_DETECTED];
63
+ }
64
+ /**
65
+ * Event for screenshot detection
66
+ */
67
+ export interface ScreenshotEvent extends ProtectionEvent {
68
+ type: ProtectionEventType.SCREENSHOT_ATTEMPT;
69
+ data: EventDataMap[ProtectionEventType.SCREENSHOT_ATTEMPT];
70
+ }
71
+ /**
72
+ * Event for frame embedding detection
73
+ */
74
+ export interface FrameEmbeddingEvent extends ProtectionEvent {
75
+ type: ProtectionEventType.FRAME_EMBEDDING_DETECTED;
76
+ data: EventDataMap[ProtectionEventType.FRAME_EMBEDDING_DETECTED];
77
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Types of protection events that can be published and subscribed to.
3
+ *
4
+ * Only the events listed below are actually wired through the mediator today.
5
+ * The mediator pattern serves a specific case: a detect-and-react fan-out where
6
+ * one detection signal needs to coordinate multiple visible reactions (overlay,
7
+ * content hiding, telemetry). That's why only 4 of the 10 strategies use it —
8
+ * DevTools, Extension, IFrame, and Screenshot. The other 6 (Clipboard,
9
+ * Selection, ContextMenu, Keyboard, Print, Watermark) are direct-blocking
10
+ * strategies where the handler IS the strategy; routing them through the
11
+ * mediator would add ceremony for no decoupling benefit.
12
+ *
13
+ * If you need a NEW event type, add it here AND give it a `[NewType]: { ... }`
14
+ * entry in {@link EventDataMap}.
15
+ */
16
+ export var ProtectionEventType;
17
+ (function (ProtectionEventType) {
18
+ // Strategy lifecycle
19
+ ProtectionEventType["STRATEGY_REMOVED"] = "strategy:removed";
20
+ // Detection signals (published by the detect-and-react strategies)
21
+ ProtectionEventType["DEVTOOLS_STATE_CHANGE"] = "protection:devtools";
22
+ ProtectionEventType["EXTENSION_DETECTED"] = "protection:extension";
23
+ ProtectionEventType["FRAME_EMBEDDING_DETECTED"] = "protection:frame";
24
+ ProtectionEventType["SCREENSHOT_ATTEMPT"] = "protection:screenshot";
25
+ // Overlay coordination
26
+ ProtectionEventType["OVERLAY_SHOWN"] = "overlay:shown";
27
+ ProtectionEventType["OVERLAY_REMOVED"] = "overlay:removed";
28
+ ProtectionEventType["OVERLAY_RESTORED"] = "overlay:restored";
29
+ // Content coordination
30
+ ProtectionEventType["CONTENT_HIDDEN"] = "content:hidden";
31
+ ProtectionEventType["CONTENT_RESTORED"] = "content:restored";
32
+ })(ProtectionEventType || (ProtectionEventType = {}));
@@ -0,0 +1,105 @@
1
+ import { EventDataMap } from './eventDataTypes';
2
+ import { ProtectionEvent, ProtectionEventType } from './protection-event';
3
+ /**
4
+ * Event handler function type
5
+ */
6
+ export type ProtectionEventHandler = (event: ProtectionEvent) => void;
7
+ /**
8
+ * Subscription information
9
+ */
10
+ export interface Subscription {
11
+ /**
12
+ * Unique ID for the subscription
13
+ */
14
+ id: string;
15
+ /**
16
+ * Event type being subscribed to
17
+ */
18
+ eventType: ProtectionEventType;
19
+ /**
20
+ * Handler function for the event
21
+ */
22
+ handler: ProtectionEventHandler;
23
+ /**
24
+ * Optional filter function to determine if the handler should be called
25
+ */
26
+ filter?: (event: ProtectionEvent) => boolean;
27
+ /**
28
+ * Optional priority for the handler (higher numbers execute first)
29
+ */
30
+ priority?: number;
31
+ /**
32
+ * Optional context information (e.g., strategy name)
33
+ */
34
+ context?: string;
35
+ }
36
+ /**
37
+ * Subscription options
38
+ */
39
+ export interface SubscriptionOptions {
40
+ /**
41
+ * Optional filter function to determine if the handler should be called
42
+ */
43
+ filter?: (event: ProtectionEvent) => boolean;
44
+ /**
45
+ * Optional priority for the handler (higher numbers execute first)
46
+ */
47
+ priority?: number;
48
+ /**
49
+ * Optional context information (e.g., strategy name)
50
+ */
51
+ context?: string;
52
+ }
53
+ /**
54
+ * Interface for the protection mediator
55
+ */
56
+ export interface ProtectionMediator {
57
+ /**
58
+ * Subscribe to an event
59
+ * @param eventType Type of event to subscribe to
60
+ * @param handler Handler function for the event
61
+ * @param options Optional subscription options
62
+ * @returns Subscription ID for later unsubscribing
63
+ */
64
+ subscribe(eventType: ProtectionEventType, handler: ProtectionEventHandler, options?: SubscriptionOptions): string;
65
+ /**
66
+ * Unsubscribe from an event
67
+ * @param subscriptionId ID of the subscription to remove
68
+ * @returns True if the subscription was found and removed
69
+ */
70
+ unsubscribe(subscriptionId: string): boolean;
71
+ /**
72
+ * Publish an event to all subscribers
73
+ * @param event Event to publish
74
+ */
75
+ publish<T extends ProtectionEventType | string>(event: Omit<ProtectionEvent, "data"> & {
76
+ type: T;
77
+ data?: T extends ProtectionEventType ? EventDataMap[T] : Record<string, unknown>;
78
+ }): void;
79
+ /**
80
+ * Get all subscriptions for a specific event type
81
+ * @param eventType Type of event to get subscriptions for
82
+ * @returns Array of subscriptions
83
+ */
84
+ getSubscriptions(eventType: ProtectionEventType): Subscription[];
85
+ /**
86
+ * Set debug mode
87
+ * @param enabled Whether debug mode should be enabled
88
+ */
89
+ setDebugMode(enabled: boolean): void;
90
+ }
91
+ /**
92
+ * Interface for components that can work with the mediator
93
+ */
94
+ export interface MediatorAware {
95
+ /**
96
+ * Set the mediator for this component
97
+ * @param mediator The protection mediator
98
+ */
99
+ setMediator(mediator: ProtectionMediator): void;
100
+ /**
101
+ * Get the component name
102
+ * Used to identify the component in mediator communications
103
+ */
104
+ readonly COMPONENT_NAME: string;
105
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ export { assess } from './assess.js';
2
+ export type { ShieldAssessment, ShieldSignals, ShieldRisk, AssessOptions } from './types/assessment.js';
3
+ export { ContentProtector } from './core/index.js';
4
+ export * from './types/index.js';
5
+ export * from './strategies/index.js';
6
+ export * from './utils/index.js';
7
+ export { attachShieldToSpan } from './otel.js';
8
+ export type { SpanEmitter } from './otel.js';
9
+ export { assessAndProtect } from './policy.js';
10
+ export type { PolicyRule, PolicyCondition, PolicyEngineOptions, PolicyResult, StrategyKey } from './policy.js';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { assess } from './assess.js';
2
+ export { ContentProtector } from './core/index.js';
3
+ export * from './types/index.js';
4
+ export * from './strategies/index.js';
5
+ export * from './utils/index.js';
6
+ export { attachShieldToSpan } from './otel.js';
7
+ export { assessAndProtect } from './policy.js';
package/dist/otel.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { ContentProtector } from '@/core/index.js';
2
+ import type { ContentProtectionOptions } from '@/types/index.js';
3
+ /**
4
+ * A function that records one Shield security event as an immediately-ending
5
+ * span (or any other sink). Keeping it framework-agnostic — Shield does not
6
+ * depend on @opentelemetry/api; callers provide the emitter.
7
+ *
8
+ * @example with Blindspot:
9
+ * import { getTracer, getRouteContext } from '@tindalabs/blindspot';
10
+ * const emitter: SpanEmitter = (name, attrs) => {
11
+ * const span = getTracer().startSpan(name, { attributes: attrs }, getRouteContext());
12
+ * span.end();
13
+ * };
14
+ */
15
+ export type SpanEmitter = (name: string, attrs?: Record<string, string | number | boolean>) => void;
16
+ /**
17
+ * Creates a ContentProtector with all callbacks wired to the provided SpanEmitter.
18
+ * Each security event fires a call to emitter(), which should create and immediately
19
+ * end a child span — so events are exported to Tempo without waiting for the
20
+ * long-lived navigation span to close.
21
+ *
22
+ * Any existing customHandlers in options are preserved and called after the emit.
23
+ */
24
+ export declare function attachShieldToSpan(options: ContentProtectionOptions, emitter: SpanEmitter): ContentProtector;