@skillsmith/core 0.9.0 → 0.11.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/CHANGELOG.md +16 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts +23 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts.map +1 -1
- package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js +137 -0
- package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js.map +1 -1
- package/dist/src/analysis/tree-sitter/pythonIncremental.js +83 -10
- package/dist/src/analysis/tree-sitter/pythonIncremental.js.map +1 -1
- package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js +6 -1
- package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js.map +1 -1
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.js +6 -0
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/api/client.test.d.ts +9 -0
- package/dist/src/api/client.test.d.ts.map +1 -0
- package/dist/src/api/client.test.js +81 -0
- package/dist/src/api/client.test.js.map +1 -0
- package/dist/src/config/audit-notify-state.d.ts +46 -0
- package/dist/src/config/audit-notify-state.d.ts.map +1 -0
- package/dist/src/config/audit-notify-state.js +55 -0
- package/dist/src/config/audit-notify-state.js.map +1 -0
- package/dist/src/config/audit-notify-state.test.d.ts +9 -0
- package/dist/src/config/audit-notify-state.test.d.ts.map +1 -0
- package/dist/src/config/audit-notify-state.test.js +63 -0
- package/dist/src/config/audit-notify-state.test.js.map +1 -0
- package/dist/src/config/index.d.ts +10 -0
- package/dist/src/config/index.d.ts.map +1 -1
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/exports/services.d.ts +3 -1
- package/dist/src/exports/services.d.ts.map +1 -1
- package/dist/src/exports/services.js +9 -1
- package/dist/src/exports/services.js.map +1 -1
- package/dist/src/index.d.ts +6 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +11 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/install/agent-config-merge.json-array.d.ts +29 -0
- package/dist/src/install/agent-config-merge.json-array.d.ts.map +1 -0
- package/dist/src/install/agent-config-merge.json-array.js +100 -0
- package/dist/src/install/agent-config-merge.json-array.js.map +1 -0
- package/dist/src/install/agent-config-merge.json.d.ts +37 -0
- package/dist/src/install/agent-config-merge.json.d.ts.map +1 -0
- package/dist/src/install/agent-config-merge.json.js +134 -0
- package/dist/src/install/agent-config-merge.json.js.map +1 -0
- package/dist/src/install/agent-config-merge.toml-block.d.ts +48 -0
- package/dist/src/install/agent-config-merge.toml-block.d.ts.map +1 -0
- package/dist/src/install/agent-config-merge.toml-block.js +107 -0
- package/dist/src/install/agent-config-merge.toml-block.js.map +1 -0
- package/dist/src/install/agent-config-merge.types.d.ts +87 -0
- package/dist/src/install/agent-config-merge.types.d.ts.map +1 -0
- package/dist/src/install/agent-config-merge.types.js +83 -0
- package/dist/src/install/agent-config-merge.types.js.map +1 -0
- package/dist/src/install/agent-config-merge.yaml.d.ts +46 -0
- package/dist/src/install/agent-config-merge.yaml.d.ts.map +1 -0
- package/dist/src/install/agent-config-merge.yaml.js +133 -0
- package/dist/src/install/agent-config-merge.yaml.js.map +1 -0
- package/dist/src/install/agent-config-merge.yaml.test.d.ts +2 -0
- package/dist/src/install/agent-config-merge.yaml.test.d.ts.map +1 -0
- package/dist/src/install/agent-config-merge.yaml.test.js +210 -0
- package/dist/src/install/agent-config-merge.yaml.test.js.map +1 -0
- package/dist/src/install/agent-harness-targets.d.ts +98 -0
- package/dist/src/install/agent-harness-targets.d.ts.map +1 -0
- package/dist/src/install/agent-harness-targets.js +154 -0
- package/dist/src/install/agent-harness-targets.js.map +1 -0
- package/dist/src/install/agent-home-relocate.d.ts +29 -0
- package/dist/src/install/agent-home-relocate.d.ts.map +1 -0
- package/dist/src/install/agent-home-relocate.js +38 -0
- package/dist/src/install/agent-home-relocate.js.map +1 -0
- package/dist/src/install/agent-manifest-path-guard.d.ts +55 -0
- package/dist/src/install/agent-manifest-path-guard.d.ts.map +1 -0
- package/dist/src/install/agent-manifest-path-guard.js +109 -0
- package/dist/src/install/agent-manifest-path-guard.js.map +1 -0
- package/dist/src/install/agent-manifest-path-guard.test.d.ts +2 -0
- package/dist/src/install/agent-manifest-path-guard.test.d.ts.map +1 -0
- package/dist/src/install/agent-manifest-path-guard.test.js +72 -0
- package/dist/src/install/agent-manifest-path-guard.test.js.map +1 -0
- package/dist/src/install/agent-manifest.d.ts +58 -0
- package/dist/src/install/agent-manifest.d.ts.map +1 -0
- package/dist/src/install/agent-manifest.js +103 -0
- package/dist/src/install/agent-manifest.js.map +1 -0
- package/dist/src/install/agent-pack-installer.d.ts +39 -0
- package/dist/src/install/agent-pack-installer.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.entry.d.ts +55 -0
- package/dist/src/install/agent-pack-installer.entry.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.entry.js +90 -0
- package/dist/src/install/agent-pack-installer.entry.js.map +1 -0
- package/dist/src/install/agent-pack-installer.fs-helpers.d.ts +33 -0
- package/dist/src/install/agent-pack-installer.fs-helpers.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.fs-helpers.js +59 -0
- package/dist/src/install/agent-pack-installer.fs-helpers.js.map +1 -0
- package/dist/src/install/agent-pack-installer.harness.d.ts +66 -0
- package/dist/src/install/agent-pack-installer.harness.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.harness.js +310 -0
- package/dist/src/install/agent-pack-installer.harness.js.map +1 -0
- package/dist/src/install/agent-pack-installer.js +221 -0
- package/dist/src/install/agent-pack-installer.js.map +1 -0
- package/dist/src/install/agent-pack-installer.preserve.test.d.ts +11 -0
- package/dist/src/install/agent-pack-installer.preserve.test.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.preserve.test.js +72 -0
- package/dist/src/install/agent-pack-installer.preserve.test.js.map +1 -0
- package/dist/src/install/agent-pack-installer.test.d.ts +2 -0
- package/dist/src/install/agent-pack-installer.test.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.test.js +350 -0
- package/dist/src/install/agent-pack-installer.test.js.map +1 -0
- package/dist/src/install/agent-pack-installer.types.d.ts +51 -0
- package/dist/src/install/agent-pack-installer.types.d.ts.map +1 -0
- package/dist/src/install/agent-pack-installer.types.js +16 -0
- package/dist/src/install/agent-pack-installer.types.js.map +1 -0
- package/dist/src/install/agent-pack-uninstaller.d.ts +43 -0
- package/dist/src/install/agent-pack-uninstaller.d.ts.map +1 -0
- package/dist/src/install/agent-pack-uninstaller.js +113 -0
- package/dist/src/install/agent-pack-uninstaller.js.map +1 -0
- package/dist/src/install/agent-pack-uninstaller.test.d.ts +2 -0
- package/dist/src/install/agent-pack-uninstaller.test.d.ts.map +1 -0
- package/dist/src/install/agent-pack-uninstaller.test.js +212 -0
- package/dist/src/install/agent-pack-uninstaller.test.js.map +1 -0
- package/dist/src/install/index.d.ts +7 -0
- package/dist/src/install/index.d.ts.map +1 -1
- package/dist/src/install/index.js +7 -0
- package/dist/src/install/index.js.map +1 -1
- package/dist/src/install/paths.d.ts +1 -1
- package/dist/src/install/paths.d.ts.map +1 -1
- package/dist/src/install/paths.js +4 -0
- package/dist/src/install/paths.js.map +1 -1
- package/dist/src/install/paths.test.js +15 -0
- package/dist/src/install/paths.test.js.map +1 -1
- package/dist/src/journal/hash.d.ts +13 -0
- package/dist/src/journal/hash.d.ts.map +1 -0
- package/dist/src/journal/hash.js +16 -0
- package/dist/src/journal/hash.js.map +1 -0
- package/dist/src/journal/index.d.ts +15 -0
- package/dist/src/journal/index.d.ts.map +1 -0
- package/dist/src/journal/index.js +15 -0
- package/dist/src/journal/index.js.map +1 -0
- package/dist/src/journal/journal.test.d.ts +16 -0
- package/dist/src/journal/journal.test.d.ts.map +1 -0
- package/dist/src/journal/journal.test.js +171 -0
- package/dist/src/journal/journal.test.js.map +1 -0
- package/dist/src/journal/path.d.ts +44 -0
- package/dist/src/journal/path.d.ts.map +1 -0
- package/dist/src/journal/path.js +61 -0
- package/dist/src/journal/path.js.map +1 -0
- package/dist/src/journal/reader.d.ts +38 -0
- package/dist/src/journal/reader.d.ts.map +1 -0
- package/dist/src/journal/reader.js +93 -0
- package/dist/src/journal/reader.js.map +1 -0
- package/dist/src/journal/types.d.ts +87 -0
- package/dist/src/journal/types.d.ts.map +1 -0
- package/dist/src/journal/types.js +21 -0
- package/dist/src/journal/types.js.map +1 -0
- package/dist/src/journal/writer.d.ts +52 -0
- package/dist/src/journal/writer.d.ts.map +1 -0
- package/dist/src/journal/writer.js +125 -0
- package/dist/src/journal/writer.js.map +1 -0
- package/dist/src/logging/context.d.ts +58 -0
- package/dist/src/logging/context.d.ts.map +1 -0
- package/dist/src/logging/context.js +62 -0
- package/dist/src/logging/context.js.map +1 -0
- package/dist/src/logging/context.test.d.ts +14 -0
- package/dist/src/logging/context.test.d.ts.map +1 -0
- package/dist/src/logging/context.test.js +88 -0
- package/dist/src/logging/context.test.js.map +1 -0
- package/dist/src/logging/index.d.ts +13 -0
- package/dist/src/logging/index.d.ts.map +1 -0
- package/dist/src/logging/index.js +12 -0
- package/dist/src/logging/index.js.map +1 -0
- package/dist/src/logging/logger.d.ts +71 -0
- package/dist/src/logging/logger.d.ts.map +1 -0
- package/dist/src/logging/logger.js +264 -0
- package/dist/src/logging/logger.js.map +1 -0
- package/dist/src/logging/logger.test.d.ts +9 -0
- package/dist/src/logging/logger.test.d.ts.map +1 -0
- package/dist/src/logging/logger.test.js +320 -0
- package/dist/src/logging/logger.test.js.map +1 -0
- package/dist/src/logging/redact.d.ts +35 -0
- package/dist/src/logging/redact.d.ts.map +1 -0
- package/dist/src/logging/redact.js +152 -0
- package/dist/src/logging/redact.js.map +1 -0
- package/dist/src/logging/redact.test.d.ts +8 -0
- package/dist/src/logging/redact.test.d.ts.map +1 -0
- package/dist/src/logging/redact.test.js +330 -0
- package/dist/src/logging/redact.test.js.map +1 -0
- package/dist/src/logging/rotation.d.ts +75 -0
- package/dist/src/logging/rotation.d.ts.map +1 -0
- package/dist/src/logging/rotation.js +284 -0
- package/dist/src/logging/rotation.js.map +1 -0
- package/dist/src/logging/rotation.test.d.ts +11 -0
- package/dist/src/logging/rotation.test.d.ts.map +1 -0
- package/dist/src/logging/rotation.test.js +132 -0
- package/dist/src/logging/rotation.test.js.map +1 -0
- package/dist/src/logging/types.d.ts +69 -0
- package/dist/src/logging/types.d.ts.map +1 -0
- package/dist/src/logging/types.js +9 -0
- package/dist/src/logging/types.js.map +1 -0
- package/dist/src/paywall-triggers/index.d.ts +13 -0
- package/dist/src/paywall-triggers/index.d.ts.map +1 -0
- package/dist/src/paywall-triggers/index.js +13 -0
- package/dist/src/paywall-triggers/index.js.map +1 -0
- package/dist/src/paywall-triggers/path.d.ts +47 -0
- package/dist/src/paywall-triggers/path.d.ts.map +1 -0
- package/dist/src/paywall-triggers/path.js +73 -0
- package/dist/src/paywall-triggers/path.js.map +1 -0
- package/dist/src/paywall-triggers/store.d.ts +75 -0
- package/dist/src/paywall-triggers/store.d.ts.map +1 -0
- package/dist/src/paywall-triggers/store.js +122 -0
- package/dist/src/paywall-triggers/store.js.map +1 -0
- package/dist/src/paywall-triggers/store.test.d.ts +2 -0
- package/dist/src/paywall-triggers/store.test.d.ts.map +1 -0
- package/dist/src/paywall-triggers/store.test.js +121 -0
- package/dist/src/paywall-triggers/store.test.js.map +1 -0
- package/dist/src/paywall-triggers/types.d.ts +24 -0
- package/dist/src/paywall-triggers/types.d.ts.map +1 -0
- package/dist/src/paywall-triggers/types.js +13 -0
- package/dist/src/paywall-triggers/types.js.map +1 -0
- package/dist/src/security/index.d.ts +2 -0
- package/dist/src/security/index.d.ts.map +1 -1
- package/dist/src/security/index.js +4 -0
- package/dist/src/security/index.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.compound.d.ts +13 -0
- package/dist/src/security/scanner/SecurityScanner.compound.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.compound.js +127 -0
- package/dist/src/security/scanner/SecurityScanner.compound.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.hostile-update.d.ts +46 -0
- package/dist/src/security/scanner/SecurityScanner.hostile-update.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.hostile-update.js +209 -0
- package/dist/src/security/scanner/SecurityScanner.hostile-update.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.js +10 -1
- package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.pii.d.ts +23 -0
- package/dist/src/security/scanner/SecurityScanner.pii.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.pii.js +152 -0
- package/dist/src/security/scanner/SecurityScanner.pii.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.scanners.d.ts +5 -12
- package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.scanners.js +63 -137
- package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
- package/dist/src/security/scanner/index.d.ts +2 -1
- package/dist/src/security/scanner/index.d.ts.map +1 -1
- package/dist/src/security/scanner/index.js +2 -0
- package/dist/src/security/scanner/index.js.map +1 -1
- package/dist/src/security/scanner/patterns.d.ts +2 -0
- package/dist/src/security/scanner/patterns.d.ts.map +1 -1
- package/dist/src/security/scanner/patterns.js +79 -11
- package/dist/src/security/scanner/patterns.js.map +1 -1
- package/dist/src/security/scanner/types.d.ts +23 -0
- package/dist/src/security/scanner/types.d.ts.map +1 -1
- package/dist/src/services/agent-pack/agent-pack.test.d.ts +18 -0
- package/dist/src/services/agent-pack/agent-pack.test.d.ts.map +1 -0
- package/dist/src/services/agent-pack/agent-pack.test.js +344 -0
- package/dist/src/services/agent-pack/agent-pack.test.js.map +1 -0
- package/dist/src/services/agent-pack/hooks.d.ts +29 -0
- package/dist/src/services/agent-pack/hooks.d.ts.map +1 -0
- package/dist/src/services/agent-pack/hooks.js +139 -0
- package/dist/src/services/agent-pack/hooks.js.map +1 -0
- package/dist/src/services/agent-pack/index.d.ts +26 -0
- package/dist/src/services/agent-pack/index.d.ts.map +1 -0
- package/dist/src/services/agent-pack/index.js +109 -0
- package/dist/src/services/agent-pack/index.js.map +1 -0
- package/dist/src/services/agent-pack/prompt-source.d.ts +47 -0
- package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -0
- package/dist/src/services/agent-pack/prompt-source.js +182 -0
- package/dist/src/services/agent-pack/prompt-source.js.map +1 -0
- package/dist/src/services/agent-pack/shims.d.ts +40 -0
- package/dist/src/services/agent-pack/shims.d.ts.map +1 -0
- package/dist/src/services/agent-pack/shims.js +96 -0
- package/dist/src/services/agent-pack/shims.js.map +1 -0
- package/dist/src/services/agent-pack/skill-md.d.ts +35 -0
- package/dist/src/services/agent-pack/skill-md.d.ts.map +1 -0
- package/dist/src/services/agent-pack/skill-md.js +89 -0
- package/dist/src/services/agent-pack/skill-md.js.map +1 -0
- package/dist/src/services/agent-pack/types.d.ts +118 -0
- package/dist/src/services/agent-pack/types.d.ts.map +1 -0
- package/dist/src/services/agent-pack/types.js +61 -0
- package/dist/src/services/agent-pack/types.js.map +1 -0
- package/dist/src/services/agent-tool-profile.d.ts +59 -0
- package/dist/src/services/agent-tool-profile.d.ts.map +1 -0
- package/dist/src/services/agent-tool-profile.js +76 -0
- package/dist/src/services/agent-tool-profile.js.map +1 -0
- package/dist/src/services/agent-tool-profile.test.d.ts +2 -0
- package/dist/src/services/agent-tool-profile.test.d.ts.map +1 -0
- package/dist/src/services/agent-tool-profile.test.js +28 -0
- package/dist/src/services/agent-tool-profile.test.js.map +1 -0
- package/dist/src/services/bundled-sibling-scan.d.ts +111 -0
- package/dist/src/services/bundled-sibling-scan.d.ts.map +1 -0
- package/dist/src/services/bundled-sibling-scan.js +170 -0
- package/dist/src/services/bundled-sibling-scan.js.map +1 -0
- package/dist/src/services/skill-installation.io.d.ts +16 -5
- package/dist/src/services/skill-installation.io.d.ts.map +1 -1
- package/dist/src/services/skill-installation.io.js +63 -22
- package/dist/src/services/skill-installation.io.js.map +1 -1
- package/dist/src/services/skill-installation.policy.d.ts +96 -0
- package/dist/src/services/skill-installation.policy.d.ts.map +1 -0
- package/dist/src/services/skill-installation.policy.js +144 -0
- package/dist/src/services/skill-installation.policy.js.map +1 -0
- package/dist/src/services/skill-installation.service.d.ts.map +1 -1
- package/dist/src/services/skill-installation.service.js +9 -3
- package/dist/src/services/skill-installation.service.js.map +1 -1
- package/dist/src/sources/index.d.ts +1 -0
- package/dist/src/sources/index.d.ts.map +1 -1
- package/dist/src/sources/index.js +4 -0
- package/dist/src/sources/index.js.map +1 -1
- package/dist/src/sync/access-token.d.ts +27 -0
- package/dist/src/sync/access-token.d.ts.map +1 -0
- package/dist/src/sync/access-token.js +40 -0
- package/dist/src/sync/access-token.js.map +1 -0
- package/dist/src/sync/audit-notify-client.d.ts +83 -0
- package/dist/src/sync/audit-notify-client.d.ts.map +1 -0
- package/dist/src/sync/audit-notify-client.js +126 -0
- package/dist/src/sync/audit-notify-client.js.map +1 -0
- package/dist/src/sync/audit-notify-client.test.d.ts +14 -0
- package/dist/src/sync/audit-notify-client.test.d.ts.map +1 -0
- package/dist/src/sync/audit-notify-client.test.js +133 -0
- package/dist/src/sync/audit-notify-client.test.js.map +1 -0
- package/dist/src/sync/index.d.ts +2 -1
- package/dist/src/sync/index.d.ts.map +1 -1
- package/dist/src/sync/index.js +3 -1
- package/dist/src/sync/index.js.map +1 -1
- package/dist/src/sync/inventory-client.d.ts +16 -0
- package/dist/src/sync/inventory-client.d.ts.map +1 -1
- package/dist/src/sync/inventory-client.js +59 -16
- package/dist/src/sync/inventory-client.js.map +1 -1
- package/dist/src/sync/inventory-client.test.js +67 -1
- package/dist/src/sync/inventory-client.test.js.map +1 -1
- package/dist/src/sync/inventory-collector.d.ts.map +1 -1
- package/dist/src/sync/inventory-collector.js +32 -5
- package/dist/src/sync/inventory-collector.js.map +1 -1
- package/dist/src/sync/inventory-collector.test.js +50 -1
- package/dist/src/sync/inventory-collector.test.js.map +1 -1
- package/dist/src/sync/inventory-types.d.ts +9 -0
- package/dist/src/sync/inventory-types.d.ts.map +1 -1
- package/dist/src/sync/inventory-types.js +3 -0
- package/dist/src/sync/inventory-types.js.map +1 -1
- package/dist/src/telemetry/agent-marker.d.ts +137 -0
- package/dist/src/telemetry/agent-marker.d.ts.map +1 -0
- package/dist/src/telemetry/agent-marker.js +242 -0
- package/dist/src/telemetry/agent-marker.js.map +1 -0
- package/dist/src/telemetry/agent-marker.test.d.ts +13 -0
- package/dist/src/telemetry/agent-marker.test.d.ts.map +1 -0
- package/dist/src/telemetry/agent-marker.test.js +202 -0
- package/dist/src/telemetry/agent-marker.test.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +2 -1
- package/dist/src/telemetry/index.d.ts.map +1 -1
- package/dist/src/telemetry/index.js +6 -1
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/posthog.d.ts +25 -0
- package/dist/src/telemetry/posthog.d.ts.map +1 -1
- package/dist/src/telemetry/posthog.js +10 -1
- package/dist/src/telemetry/posthog.js.map +1 -1
- package/dist/src/telemetry/wrap.bench.js +5 -0
- package/dist/src/telemetry/wrap.bench.js.map +1 -1
- package/dist/src/telemetry/wrap.correlation.test.d.ts +20 -0
- package/dist/src/telemetry/wrap.correlation.test.d.ts.map +1 -0
- package/dist/src/telemetry/wrap.correlation.test.js +174 -0
- package/dist/src/telemetry/wrap.correlation.test.js.map +1 -0
- package/dist/src/telemetry/wrap.d.ts +28 -7
- package/dist/src/telemetry/wrap.d.ts.map +1 -1
- package/dist/src/telemetry/wrap.gate.test.d.ts +22 -0
- package/dist/src/telemetry/wrap.gate.test.d.ts.map +1 -0
- package/dist/src/telemetry/wrap.gate.test.js +202 -0
- package/dist/src/telemetry/wrap.gate.test.js.map +1 -0
- package/dist/src/telemetry/wrap.js +196 -52
- package/dist/src/telemetry/wrap.js.map +1 -1
- package/dist/src/telemetry/wrap.marker.test.d.ts +16 -0
- package/dist/src/telemetry/wrap.marker.test.d.ts.map +1 -0
- package/dist/src/telemetry/wrap.marker.test.js +190 -0
- package/dist/src/telemetry/wrap.marker.test.js.map +1 -0
- package/dist/src/telemetry/wrap.test.js +14 -0
- package/dist/src/telemetry/wrap.test.js.map +1 -1
- package/dist/src/types.d.ts +6 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tests/SecurityScanner.exec.test.js +60 -0
- package/dist/tests/SecurityScanner.exec.test.js.map +1 -1
- package/dist/tests/security/ContinuousSecurity.test.js +10 -4
- package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
- package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts +2 -0
- package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts.map +1 -0
- package/dist/tests/security/SecurityScanner.chmod-evasion.test.js +126 -0
- package/dist/tests/security/SecurityScanner.chmod-evasion.test.js.map +1 -0
- package/dist/tests/security/chmod-compound.test.d.ts +2 -0
- package/dist/tests/security/chmod-compound.test.d.ts.map +1 -0
- package/dist/tests/security/chmod-compound.test.js +188 -0
- package/dist/tests/security/chmod-compound.test.js.map +1 -0
- package/dist/tests/security/pii-detection.test.js +24 -0
- package/dist/tests/security/pii-detection.test.js.map +1 -1
- package/dist/tests/security/scanner-regression-guard.test.d.ts +23 -7
- package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
- package/dist/tests/security/scanner-regression-guard.test.js +206 -12
- package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
- package/dist/tests/security/sensitive-path-fp.test.d.ts +2 -0
- package/dist/tests/security/sensitive-path-fp.test.d.ts.map +1 -0
- package/dist/tests/security/sensitive-path-fp.test.js +142 -0
- package/dist/tests/security/sensitive-path-fp.test.js.map +1 -0
- package/dist/tests/services/bundled-sibling-scan.test.d.ts +2 -0
- package/dist/tests/services/bundled-sibling-scan.test.d.ts.map +1 -0
- package/dist/tests/services/bundled-sibling-scan.test.js +139 -0
- package/dist/tests/services/bundled-sibling-scan.test.js.map +1 -0
- package/dist/tests/unit/services/skill-installation.io.test.js +166 -0
- package/dist/tests/unit/services/skill-installation.io.test.js.map +1 -1
- package/dist/tests/unit/services/skill-installation.policy.test.d.ts +8 -0
- package/dist/tests/unit/services/skill-installation.policy.test.d.ts.map +1 -0
- package/dist/tests/unit/services/skill-installation.policy.test.js +151 -0
- package/dist/tests/unit/services/skill-installation.policy.test.js.map +1 -0
- package/package.json +28 -3
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigger-state file layout (SMI-5456 Wave 1 Step 5, QD-3).
|
|
3
|
+
*
|
|
4
|
+
* `~/.skillsmith/paywall-triggers/<triggerId>.json` — one file per trigger,
|
|
5
|
+
* mirroring the per-resource-directory convention already used by
|
|
6
|
+
* `journal/path.ts` (`~/.skillsmith/journal/`) and
|
|
7
|
+
* `telemetry/agent-marker.ts` (`~/.skillsmith/agent-markers/`). Named
|
|
8
|
+
* `paywall-triggers` (not `triggers`) both in the module path and the
|
|
9
|
+
* on-disk directory to avoid any collision with the PRE-EXISTING, unrelated
|
|
10
|
+
* `packages/core/src/triggers/` module (`TriggerDetector`/`ContextScorer` —
|
|
11
|
+
* proactive skill-suggestion detection, nothing to do with PRD §8.1's T1-T4
|
|
12
|
+
* paywall triggers).
|
|
13
|
+
*
|
|
14
|
+
* Format compatibility with the SessionStart hook's nudge cooldown
|
|
15
|
+
* (the per-harness `hooks/<harness>/session-start.sh` script, generated by
|
|
16
|
+
* the — locked for this step — `agent-pack/hooks.ts`): that hook writes a
|
|
17
|
+
* PLAIN epoch-seconds integer to
|
|
18
|
+
* `~/.skillsmith/agent-nudge.state` (`SKILLSMITH_AGENT_NUDGE_STATE`
|
|
19
|
+
* override), because it is self-contained POSIX sh with no JSON tooling
|
|
20
|
+
* available. This module's {@link getNudgeCooldownState} reads that EXACT
|
|
21
|
+
* file/format/override so a future consumer (a report, a diagnostic) can
|
|
22
|
+
* inspect the onboarding-nudge cooldown through the same TS surface as the
|
|
23
|
+
* T1-T4 paywall triggers, without asking the hook to change its wire format.
|
|
24
|
+
* The T1-T4 trigger files themselves are independent, JSON-shaped, and own
|
|
25
|
+
* their own directory — see the module header of `store.ts` for why.
|
|
26
|
+
*
|
|
27
|
+
* @module @skillsmith/core/paywall-triggers/path
|
|
28
|
+
*/
|
|
29
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
30
|
+
import { join } from 'node:path';
|
|
31
|
+
import { getConfigDir } from '../config/index.js';
|
|
32
|
+
/** Env var overriding the trigger-state directory (test isolation). */
|
|
33
|
+
export const TRIGGER_STATE_DIR_ENV_VAR = 'SKILLSMITH_TRIGGER_STATE_DIR';
|
|
34
|
+
function getTriggerStateDir() {
|
|
35
|
+
const override = process.env[TRIGGER_STATE_DIR_ENV_VAR];
|
|
36
|
+
return override && override.length > 0 ? override : join(getConfigDir(), 'paywall-triggers');
|
|
37
|
+
}
|
|
38
|
+
export function getTriggerStateFilePath(triggerId) {
|
|
39
|
+
return join(getTriggerStateDir(), `${triggerId}.json`);
|
|
40
|
+
}
|
|
41
|
+
export function getTriggerStateDirForTests() {
|
|
42
|
+
return getTriggerStateDir();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read the onboarding SessionStart hook's nudge-cooldown stamp — the SAME
|
|
46
|
+
* file (`~/.skillsmith/agent-nudge.state`, override
|
|
47
|
+
* `SKILLSMITH_AGENT_NUDGE_STATE`) `hooks.ts`'s `renderSessionStartHook`
|
|
48
|
+
* writes a bare epoch-seconds integer into. Read-only: this module never
|
|
49
|
+
* writes this file — that stays the hook's job.
|
|
50
|
+
*
|
|
51
|
+
* @returns the last-nudge epoch-seconds, or null if the file is absent,
|
|
52
|
+
* empty, or not a valid non-negative integer (matches the hook's own
|
|
53
|
+
* tolerant `case "" | *[!0-9]*) last=0` parsing — malformed content is
|
|
54
|
+
* treated as "no prior nudge", never an error).
|
|
55
|
+
*/
|
|
56
|
+
export function getNudgeCooldownState() {
|
|
57
|
+
const override = process.env.SKILLSMITH_AGENT_NUDGE_STATE;
|
|
58
|
+
const path = override && override.length > 0 ? override : join(getConfigDir(), 'agent-nudge.state');
|
|
59
|
+
if (!existsSync(path))
|
|
60
|
+
return null;
|
|
61
|
+
let raw;
|
|
62
|
+
try {
|
|
63
|
+
raw = readFileSync(path, 'utf-8').trim();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
if (!/^[0-9]+$/.test(raw))
|
|
69
|
+
return null;
|
|
70
|
+
const value = Number(raw);
|
|
71
|
+
return Number.isSafeInteger(value) ? value : null;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/paywall-triggers/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGjD,uEAAuE;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,8BAA8B,CAAA;AAEvE,SAAS,kBAAkB;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;IACvD,OAAO,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAA;AAC9F,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,SAAoB;IAC1D,OAAO,IAAI,CAAC,kBAAkB,EAAE,EAAE,GAAG,SAAS,OAAO,CAAC,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO,kBAAkB,EAAE,CAAA;AAC7B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAA;IACzD,MAAM,IAAI,GACR,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,mBAAmB,CAAC,CAAA;IACxF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IACzB,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AACnD,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paywall trigger-state store (SMI-5456 Wave 1 Step 5, QD-3).
|
|
3
|
+
*
|
|
4
|
+
* PRD §8.1 defines four paywall triggers (T1 version currency, T2 quota
|
|
5
|
+
* forecast, T3 sharing, T4 security-depth disclosure) with two frequency
|
|
6
|
+
* rules: at most one upgrade prompt per session, and two dismissals of the
|
|
7
|
+
* same trigger suppress it for 30 days. This module persists the state those
|
|
8
|
+
* rules need — per-trigger last-shown session id, dismissal count, and mute
|
|
9
|
+
* expiry — under `~/.skillsmith/paywall-triggers/` (deliberately NOT
|
|
10
|
+
* `~/.skillsmith/triggers/` — see `path.ts`'s header for the pre-existing,
|
|
11
|
+
* unrelated `packages/core/src/triggers/` module this avoids colliding with).
|
|
12
|
+
*
|
|
13
|
+
* WAVE-1 SCOPE LIMITATION (read before wiring this into anything):
|
|
14
|
+
* The trigger RULES live in the pack's prompt wording (PRD §6 change 6) —
|
|
15
|
+
* the agent, running inside whatever harness's model, decides in
|
|
16
|
+
* conversation whether to mention a trigger, and the user's response
|
|
17
|
+
* ("no thanks") is plain conversational text the agent sees, not a
|
|
18
|
+
* structured tool call. There is currently NO MCP tool or CLI command that
|
|
19
|
+
* reports a T1/T2/T4 dismissal from that conversation into this store — no
|
|
20
|
+
* Wave-1 exclusion-9 tool covers it (PRD §10 exclusion 9's only two
|
|
21
|
+
* acknowledged exceptions are the undo tool and the Wave-2 stats surface).
|
|
22
|
+
* That means: {@link recordTriggerDismissal} is real, tested infrastructure
|
|
23
|
+
* with NO live caller in Wave 1. This is intentional staged infrastructure
|
|
24
|
+
* (the same shape the change-journal module shipped in — Step 3, before the
|
|
25
|
+
* apply tools became its first real caller in a later step) — NOT an
|
|
26
|
+
* "unconsumed dismissal-recording pathway" in the house anti-pattern sense,
|
|
27
|
+
* because nothing in this codebase currently calls it as if dismissals were
|
|
28
|
+
* being captured. Do not present in-conversation dismissal tracking as a
|
|
29
|
+
* shipped product behavior (docs, marketing copy, the eval-matrix report)
|
|
30
|
+
* until a real consumer exists. What DOES already work end-to-end in Wave 1:
|
|
31
|
+
* the session-cap half via {@link canShowTrigger}/{@link recordImpression} —
|
|
32
|
+
* though even that has no live caller yet either, since trigger *display*
|
|
33
|
+
* also currently lives entirely in the pack's prompt wording. Both halves
|
|
34
|
+
* are ready for whichever surface (a future tool, or a CLI diagnostic) needs
|
|
35
|
+
* them; the eval-matrix worker (Step 6) should treat "trigger frequency cap
|
|
36
|
+
* enforced server-side" as NOT YET TRUE for the published Tier badges.
|
|
37
|
+
*
|
|
38
|
+
* Single-writer-per-trigger-file note: like the journal (P-5), each trigger
|
|
39
|
+
* file is read-modify-written directly (not append-only, since there's only
|
|
40
|
+
* ever one live state per trigger, not a growing log) — concurrent writers
|
|
41
|
+
* to the SAME trigger id are not expected in Wave 1 (no live caller), so no
|
|
42
|
+
* write-queue serialization is implemented here; add one if/when a consumer
|
|
43
|
+
* with real concurrency (e.g. two parallel MCP requests) lands.
|
|
44
|
+
*
|
|
45
|
+
* @module @skillsmith/core/paywall-triggers/store
|
|
46
|
+
*/
|
|
47
|
+
import { type TriggerId, type TriggerState } from './types.js';
|
|
48
|
+
/** Load a trigger's persisted state, or a fresh empty state if none exists or it is corrupt. */
|
|
49
|
+
export declare function loadTriggerState(triggerId: TriggerId): TriggerState;
|
|
50
|
+
/**
|
|
51
|
+
* Is `triggerId` currently muted (30-day suppression after
|
|
52
|
+
* {@link TRIGGER_DISMISSAL_THRESHOLD} dismissals)?
|
|
53
|
+
*
|
|
54
|
+
* @param now - injectable clock for tests.
|
|
55
|
+
*/
|
|
56
|
+
export declare function isTriggerMuted(state: TriggerState, now?: number): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* P-5 "one prompt per session enforced from persisted state, not memory":
|
|
59
|
+
* true when `triggerId` has NOT already been shown in `sessionId` AND is not
|
|
60
|
+
* currently muted. Concurrent sessions may each independently see `true` and
|
|
61
|
+
* both prompt once — accepted, documented (P-5 table).
|
|
62
|
+
*/
|
|
63
|
+
export declare function canShowTrigger(triggerId: TriggerId, sessionId: string, now?: number): boolean;
|
|
64
|
+
/** Record that `triggerId` was shown in `sessionId` (persisted — the session cap). */
|
|
65
|
+
export declare function recordImpression(triggerId: TriggerId, sessionId: string): TriggerState;
|
|
66
|
+
/**
|
|
67
|
+
* Record a dismissal. On reaching {@link TRIGGER_DISMISSAL_THRESHOLD}
|
|
68
|
+
* dismissals, sets a {@link TRIGGER_MUTE_DAYS}-day mute from `now`.
|
|
69
|
+
*
|
|
70
|
+
* See the module header: no Wave-1 caller reports a real in-conversation
|
|
71
|
+
* dismissal today. This function is correct, tested library code — not an
|
|
72
|
+
* inert stub — for whichever surface becomes that caller.
|
|
73
|
+
*/
|
|
74
|
+
export declare function recordTriggerDismissal(triggerId: TriggerId, now?: number): TriggerState;
|
|
75
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/paywall-triggers/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAMH,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,YAAY,CAAA;AAInB,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,YAAY,CAiBnE;AAQD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAErF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAIT;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAKtF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,SAAS,EACpB,GAAG,GAAE,MAAmB,GACvB,YAAY,CAQd"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paywall trigger-state store (SMI-5456 Wave 1 Step 5, QD-3).
|
|
3
|
+
*
|
|
4
|
+
* PRD §8.1 defines four paywall triggers (T1 version currency, T2 quota
|
|
5
|
+
* forecast, T3 sharing, T4 security-depth disclosure) with two frequency
|
|
6
|
+
* rules: at most one upgrade prompt per session, and two dismissals of the
|
|
7
|
+
* same trigger suppress it for 30 days. This module persists the state those
|
|
8
|
+
* rules need — per-trigger last-shown session id, dismissal count, and mute
|
|
9
|
+
* expiry — under `~/.skillsmith/paywall-triggers/` (deliberately NOT
|
|
10
|
+
* `~/.skillsmith/triggers/` — see `path.ts`'s header for the pre-existing,
|
|
11
|
+
* unrelated `packages/core/src/triggers/` module this avoids colliding with).
|
|
12
|
+
*
|
|
13
|
+
* WAVE-1 SCOPE LIMITATION (read before wiring this into anything):
|
|
14
|
+
* The trigger RULES live in the pack's prompt wording (PRD §6 change 6) —
|
|
15
|
+
* the agent, running inside whatever harness's model, decides in
|
|
16
|
+
* conversation whether to mention a trigger, and the user's response
|
|
17
|
+
* ("no thanks") is plain conversational text the agent sees, not a
|
|
18
|
+
* structured tool call. There is currently NO MCP tool or CLI command that
|
|
19
|
+
* reports a T1/T2/T4 dismissal from that conversation into this store — no
|
|
20
|
+
* Wave-1 exclusion-9 tool covers it (PRD §10 exclusion 9's only two
|
|
21
|
+
* acknowledged exceptions are the undo tool and the Wave-2 stats surface).
|
|
22
|
+
* That means: {@link recordTriggerDismissal} is real, tested infrastructure
|
|
23
|
+
* with NO live caller in Wave 1. This is intentional staged infrastructure
|
|
24
|
+
* (the same shape the change-journal module shipped in — Step 3, before the
|
|
25
|
+
* apply tools became its first real caller in a later step) — NOT an
|
|
26
|
+
* "unconsumed dismissal-recording pathway" in the house anti-pattern sense,
|
|
27
|
+
* because nothing in this codebase currently calls it as if dismissals were
|
|
28
|
+
* being captured. Do not present in-conversation dismissal tracking as a
|
|
29
|
+
* shipped product behavior (docs, marketing copy, the eval-matrix report)
|
|
30
|
+
* until a real consumer exists. What DOES already work end-to-end in Wave 1:
|
|
31
|
+
* the session-cap half via {@link canShowTrigger}/{@link recordImpression} —
|
|
32
|
+
* though even that has no live caller yet either, since trigger *display*
|
|
33
|
+
* also currently lives entirely in the pack's prompt wording. Both halves
|
|
34
|
+
* are ready for whichever surface (a future tool, or a CLI diagnostic) needs
|
|
35
|
+
* them; the eval-matrix worker (Step 6) should treat "trigger frequency cap
|
|
36
|
+
* enforced server-side" as NOT YET TRUE for the published Tier badges.
|
|
37
|
+
*
|
|
38
|
+
* Single-writer-per-trigger-file note: like the journal (P-5), each trigger
|
|
39
|
+
* file is read-modify-written directly (not append-only, since there's only
|
|
40
|
+
* ever one live state per trigger, not a growing log) — concurrent writers
|
|
41
|
+
* to the SAME trigger id are not expected in Wave 1 (no live caller), so no
|
|
42
|
+
* write-queue serialization is implemented here; add one if/when a consumer
|
|
43
|
+
* with real concurrency (e.g. two parallel MCP requests) lands.
|
|
44
|
+
*
|
|
45
|
+
* @module @skillsmith/core/paywall-triggers/store
|
|
46
|
+
*/
|
|
47
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
48
|
+
import { dirname } from 'node:path';
|
|
49
|
+
import { getTriggerStateFilePath } from './path.js';
|
|
50
|
+
import { TRIGGER_DISMISSAL_THRESHOLD, TRIGGER_MUTE_DAYS, emptyTriggerState, } from './types.js';
|
|
51
|
+
const MUTE_DURATION_MS = TRIGGER_MUTE_DAYS * 24 * 60 * 60 * 1000;
|
|
52
|
+
/** Load a trigger's persisted state, or a fresh empty state if none exists or it is corrupt. */
|
|
53
|
+
export function loadTriggerState(triggerId) {
|
|
54
|
+
const path = getTriggerStateFilePath(triggerId);
|
|
55
|
+
if (!existsSync(path))
|
|
56
|
+
return emptyTriggerState(triggerId);
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(readFileSync(path, 'utf-8'));
|
|
59
|
+
if (parsed.triggerId !== triggerId)
|
|
60
|
+
return emptyTriggerState(triggerId);
|
|
61
|
+
return {
|
|
62
|
+
schema: 1,
|
|
63
|
+
triggerId,
|
|
64
|
+
lastSessionShown: typeof parsed.lastSessionShown === 'string' ? parsed.lastSessionShown : null,
|
|
65
|
+
dismissalCount: typeof parsed.dismissalCount === 'number' ? parsed.dismissalCount : 0,
|
|
66
|
+
mutedUntil: typeof parsed.mutedUntil === 'number' ? parsed.mutedUntil : null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return emptyTriggerState(triggerId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function saveTriggerState(state) {
|
|
74
|
+
const path = getTriggerStateFilePath(state.triggerId);
|
|
75
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
76
|
+
writeFileSync(path, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Is `triggerId` currently muted (30-day suppression after
|
|
80
|
+
* {@link TRIGGER_DISMISSAL_THRESHOLD} dismissals)?
|
|
81
|
+
*
|
|
82
|
+
* @param now - injectable clock for tests.
|
|
83
|
+
*/
|
|
84
|
+
export function isTriggerMuted(state, now = Date.now()) {
|
|
85
|
+
return state.mutedUntil !== null && now < state.mutedUntil;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* P-5 "one prompt per session enforced from persisted state, not memory":
|
|
89
|
+
* true when `triggerId` has NOT already been shown in `sessionId` AND is not
|
|
90
|
+
* currently muted. Concurrent sessions may each independently see `true` and
|
|
91
|
+
* both prompt once — accepted, documented (P-5 table).
|
|
92
|
+
*/
|
|
93
|
+
export function canShowTrigger(triggerId, sessionId, now = Date.now()) {
|
|
94
|
+
const state = loadTriggerState(triggerId);
|
|
95
|
+
if (isTriggerMuted(state, now))
|
|
96
|
+
return false;
|
|
97
|
+
return state.lastSessionShown !== sessionId;
|
|
98
|
+
}
|
|
99
|
+
/** Record that `triggerId` was shown in `sessionId` (persisted — the session cap). */
|
|
100
|
+
export function recordImpression(triggerId, sessionId) {
|
|
101
|
+
const state = loadTriggerState(triggerId);
|
|
102
|
+
const next = { ...state, lastSessionShown: sessionId };
|
|
103
|
+
saveTriggerState(next);
|
|
104
|
+
return next;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Record a dismissal. On reaching {@link TRIGGER_DISMISSAL_THRESHOLD}
|
|
108
|
+
* dismissals, sets a {@link TRIGGER_MUTE_DAYS}-day mute from `now`.
|
|
109
|
+
*
|
|
110
|
+
* See the module header: no Wave-1 caller reports a real in-conversation
|
|
111
|
+
* dismissal today. This function is correct, tested library code — not an
|
|
112
|
+
* inert stub — for whichever surface becomes that caller.
|
|
113
|
+
*/
|
|
114
|
+
export function recordTriggerDismissal(triggerId, now = Date.now()) {
|
|
115
|
+
const state = loadTriggerState(triggerId);
|
|
116
|
+
const dismissalCount = state.dismissalCount + 1;
|
|
117
|
+
const mutedUntil = dismissalCount >= TRIGGER_DISMISSAL_THRESHOLD ? now + MUTE_DURATION_MS : state.mutedUntil;
|
|
118
|
+
const next = { ...state, dismissalCount, mutedUntil };
|
|
119
|
+
saveTriggerState(next);
|
|
120
|
+
return next;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/paywall-triggers/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,iBAAiB,GAGlB,MAAM,YAAY,CAAA;AAEnB,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAEhE,gGAAgG;AAChG,MAAM,UAAU,gBAAgB,CAAC,SAAoB;IACnD,MAAM,IAAI,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAA;IAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAA;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAA0B,CAAA;QAC/E,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;YAAE,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAA;QACvE,OAAO;YACL,MAAM,EAAE,CAAC;YACT,SAAS;YACT,gBAAgB,EACd,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI;YAC9E,cAAc,EAAE,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACrF,UAAU,EAAE,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;SAC7E,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAA;IACrC,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAmB;IAC3C,MAAM,IAAI,GAAG,uBAAuB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACrD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1D,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAmB,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAC1E,OAAO,KAAK,CAAC,UAAU,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,CAAC,UAAU,CAAA;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAoB,EACpB,SAAiB,EACjB,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAA;IACzC,IAAI,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAC5C,OAAO,KAAK,CAAC,gBAAgB,KAAK,SAAS,CAAA;AAC7C,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,gBAAgB,CAAC,SAAoB,EAAE,SAAiB;IACtE,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAA;IACzC,MAAM,IAAI,GAAiB,EAAE,GAAG,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAA;IACpE,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACtB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAoB,EACpB,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAA;IACzC,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,GAAG,CAAC,CAAA;IAC/C,MAAM,UAAU,GACd,cAAc,IAAI,2BAA2B,CAAC,CAAC,CAAC,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAA;IAC3F,MAAM,IAAI,GAAiB,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,CAAA;IACnE,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACtB,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../../src/paywall-triggers/store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for the paywall trigger-state store (SMI-5456 Wave 1
|
|
3
|
+
* Step 5, QD-3). Covers the P-5 "Trigger state" invariant:
|
|
4
|
+
* "One prompt per session enforced from persisted state, not
|
|
5
|
+
* memory" (cap) + "30-day mute expiry" test.
|
|
6
|
+
* @module @skillsmith/core/paywall-triggers/store.test
|
|
7
|
+
*/
|
|
8
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
12
|
+
import { canShowTrigger, getNudgeCooldownState, isTriggerMuted, loadTriggerState, recordImpression, recordTriggerDismissal, TRIGGER_DISMISSAL_THRESHOLD, TRIGGER_MUTE_DAYS, TRIGGER_STATE_DIR_ENV_VAR, } from './index.js';
|
|
13
|
+
let stateDir;
|
|
14
|
+
let prevEnv;
|
|
15
|
+
let prevNudgeEnv;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
stateDir = mkdtempSync(join(tmpdir(), 'skillsmith-paywall-triggers-'));
|
|
18
|
+
prevEnv = process.env[TRIGGER_STATE_DIR_ENV_VAR];
|
|
19
|
+
process.env[TRIGGER_STATE_DIR_ENV_VAR] = stateDir;
|
|
20
|
+
prevNudgeEnv = process.env.SKILLSMITH_AGENT_NUDGE_STATE;
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
rmSync(stateDir, { recursive: true, force: true });
|
|
24
|
+
if (prevEnv !== undefined)
|
|
25
|
+
process.env[TRIGGER_STATE_DIR_ENV_VAR] = prevEnv;
|
|
26
|
+
else
|
|
27
|
+
delete process.env[TRIGGER_STATE_DIR_ENV_VAR];
|
|
28
|
+
if (prevNudgeEnv !== undefined)
|
|
29
|
+
process.env.SKILLSMITH_AGENT_NUDGE_STATE = prevNudgeEnv;
|
|
30
|
+
else
|
|
31
|
+
delete process.env.SKILLSMITH_AGENT_NUDGE_STATE;
|
|
32
|
+
});
|
|
33
|
+
describe('session cap (persisted, not memory)', () => {
|
|
34
|
+
it('allows showing a trigger the first time in a session', () => {
|
|
35
|
+
expect(canShowTrigger('T1', 'session-a')).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
it('blocks a second impression of the same trigger in the same session', () => {
|
|
38
|
+
recordImpression('T1', 'session-a');
|
|
39
|
+
expect(canShowTrigger('T1', 'session-a')).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
it('the cap is read from persisted state, not in-memory — a fresh loadTriggerState call after recordImpression reflects it', () => {
|
|
42
|
+
recordImpression('T2', 'session-x');
|
|
43
|
+
const state = loadTriggerState('T2');
|
|
44
|
+
expect(state.lastSessionShown).toBe('session-x');
|
|
45
|
+
});
|
|
46
|
+
it('allows the SAME trigger again in a DIFFERENT session (documented: concurrent sessions may each prompt once)', () => {
|
|
47
|
+
recordImpression('T1', 'session-a');
|
|
48
|
+
expect(canShowTrigger('T1', 'session-b')).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it('caps are independent per trigger id', () => {
|
|
51
|
+
recordImpression('T1', 'session-a');
|
|
52
|
+
expect(canShowTrigger('T3', 'session-a')).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('30-day mute expiry', () => {
|
|
56
|
+
it('does not mute after one dismissal', () => {
|
|
57
|
+
const state = recordTriggerDismissal('T4');
|
|
58
|
+
expect(state.dismissalCount).toBe(1);
|
|
59
|
+
expect(isTriggerMuted(state)).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
it(`mutes after ${TRIGGER_DISMISSAL_THRESHOLD} dismissals`, () => {
|
|
62
|
+
recordTriggerDismissal('T4');
|
|
63
|
+
const state = recordTriggerDismissal('T4');
|
|
64
|
+
expect(state.dismissalCount).toBe(TRIGGER_DISMISSAL_THRESHOLD);
|
|
65
|
+
expect(isTriggerMuted(state)).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('a muted trigger cannot be shown, even in a session it was never shown in', () => {
|
|
68
|
+
recordTriggerDismissal('T1');
|
|
69
|
+
recordTriggerDismissal('T1');
|
|
70
|
+
expect(canShowTrigger('T1', 'brand-new-session')).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
it(`is still muted 1ms before ${TRIGGER_MUTE_DAYS} days elapse`, () => {
|
|
73
|
+
const now = 1_000_000;
|
|
74
|
+
recordTriggerDismissal('T2', now);
|
|
75
|
+
recordTriggerDismissal('T2', now);
|
|
76
|
+
const almostExpired = now + TRIGGER_MUTE_DAYS * 24 * 60 * 60 * 1000 - 1;
|
|
77
|
+
const state = loadTriggerState('T2');
|
|
78
|
+
expect(isTriggerMuted(state, almostExpired)).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
it(`the mute has expired exactly at ${TRIGGER_MUTE_DAYS} days`, () => {
|
|
81
|
+
const now = 1_000_000;
|
|
82
|
+
recordTriggerDismissal('T2', now);
|
|
83
|
+
recordTriggerDismissal('T2', now);
|
|
84
|
+
const exactlyExpired = now + TRIGGER_MUTE_DAYS * 24 * 60 * 60 * 1000;
|
|
85
|
+
const state = loadTriggerState('T2');
|
|
86
|
+
expect(isTriggerMuted(state, exactlyExpired)).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
it('canShowTrigger allows the trigger again once the mute has expired', () => {
|
|
89
|
+
const now = 1_000_000;
|
|
90
|
+
recordTriggerDismissal('T3', now);
|
|
91
|
+
recordTriggerDismissal('T3', now);
|
|
92
|
+
const afterMute = now + TRIGGER_MUTE_DAYS * 24 * 60 * 60 * 1000 + 1;
|
|
93
|
+
expect(canShowTrigger('T3', 'any-session', afterMute)).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
it('dismissal count keeps accumulating past the threshold (never resets)', () => {
|
|
96
|
+
recordTriggerDismissal('T1');
|
|
97
|
+
recordTriggerDismissal('T1');
|
|
98
|
+
const state = recordTriggerDismissal('T1');
|
|
99
|
+
expect(state.dismissalCount).toBe(3);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('getNudgeCooldownState — format compatibility with the SessionStart hook', () => {
|
|
103
|
+
it('returns null when the nudge-state file does not exist', () => {
|
|
104
|
+
const nudgeFile = join(stateDir, 'agent-nudge.state');
|
|
105
|
+
process.env.SKILLSMITH_AGENT_NUDGE_STATE = nudgeFile;
|
|
106
|
+
expect(getNudgeCooldownState()).toBeNull();
|
|
107
|
+
});
|
|
108
|
+
it('reads a plain epoch-seconds integer written by the hook (no JSON, no wrapper)', () => {
|
|
109
|
+
const nudgeFile = join(stateDir, 'agent-nudge.state');
|
|
110
|
+
process.env.SKILLSMITH_AGENT_NUDGE_STATE = nudgeFile;
|
|
111
|
+
writeFileSync(nudgeFile, '1735689600');
|
|
112
|
+
expect(getNudgeCooldownState()).toBe(1735689600);
|
|
113
|
+
});
|
|
114
|
+
it('treats malformed content as "no prior nudge" (matches the hook\'s own tolerant parsing)', () => {
|
|
115
|
+
const nudgeFile = join(stateDir, 'agent-nudge.state');
|
|
116
|
+
process.env.SKILLSMITH_AGENT_NUDGE_STATE = nudgeFile;
|
|
117
|
+
writeFileSync(nudgeFile, 'not-a-number');
|
|
118
|
+
expect(getNudgeCooldownState()).toBeNull();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../../src/paywall-triggers/store.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigger-state types (SMI-5456 Wave 1 Step 5, QD-3).
|
|
3
|
+
*
|
|
4
|
+
* @module @skillsmith/core/paywall-triggers/types
|
|
5
|
+
*/
|
|
6
|
+
/** Paywall trigger IDs from PRD §8.1 (T1 version currency, T2 quota forecast, T3 sharing, T4 security depth). */
|
|
7
|
+
export type TriggerId = 'T1' | 'T2' | 'T3' | 'T4';
|
|
8
|
+
/** Days a trigger stays muted after its dismissal threshold is reached (PRD §8.1 principle 2). */
|
|
9
|
+
export declare const TRIGGER_MUTE_DAYS = 30;
|
|
10
|
+
/** Dismissals before a trigger is muted (PRD §8.1: "two dismissals... suppress it for 30 days"). */
|
|
11
|
+
export declare const TRIGGER_DISMISSAL_THRESHOLD = 2;
|
|
12
|
+
/** On-disk per-trigger state (`~/.skillsmith/paywall-triggers/<id>.json`). */
|
|
13
|
+
export interface TriggerState {
|
|
14
|
+
schema: 1;
|
|
15
|
+
triggerId: TriggerId;
|
|
16
|
+
/** Session id of the last session this trigger was shown in, or null. */
|
|
17
|
+
lastSessionShown: string | null;
|
|
18
|
+
/** Total dismissal count (never resets, even after a mute expires). */
|
|
19
|
+
dismissalCount: number;
|
|
20
|
+
/** Epoch-ms the mute lifts, or null when not currently muted. */
|
|
21
|
+
mutedUntil: number | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function emptyTriggerState(triggerId: TriggerId): TriggerState;
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/paywall-triggers/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iHAAiH;AACjH,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAEjD,kGAAkG;AAClG,eAAO,MAAM,iBAAiB,KAAK,CAAA;AAEnC,oGAAoG;AACpG,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,CAAC,CAAA;IACT,SAAS,EAAE,SAAS,CAAA;IACpB,yEAAyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAA;IACtB,iEAAiE;IACjE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,YAAY,CAEpE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigger-state types (SMI-5456 Wave 1 Step 5, QD-3).
|
|
3
|
+
*
|
|
4
|
+
* @module @skillsmith/core/paywall-triggers/types
|
|
5
|
+
*/
|
|
6
|
+
/** Days a trigger stays muted after its dismissal threshold is reached (PRD §8.1 principle 2). */
|
|
7
|
+
export const TRIGGER_MUTE_DAYS = 30;
|
|
8
|
+
/** Dismissals before a trigger is muted (PRD §8.1: "two dismissals... suppress it for 30 days"). */
|
|
9
|
+
export const TRIGGER_DISMISSAL_THRESHOLD = 2;
|
|
10
|
+
export function emptyTriggerState(triggerId) {
|
|
11
|
+
return { schema: 1, triggerId, lastSessionShown: null, dismissalCount: 0, mutedUntil: null };
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/paywall-triggers/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,kGAAkG;AAClG,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAEnC,oGAAoG;AACpG,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAA;AAc5C,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AAC9F,CAAC"}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { SecurityScanner } from './scanner/index.js';
|
|
11
11
|
export type { SecurityFinding, SecurityFindingType, SecuritySeverity, ScanReport, ScannerOptions, RiskScoreBreakdown, } from './scanner/index.js';
|
|
12
|
+
export { compareScanReports, DEFAULT_RISK_THRESHOLD } from './scanner/index.js';
|
|
13
|
+
export type { HostileUpdateVerdict } from './scanner/index.js';
|
|
12
14
|
export { sanitizeHtml, sanitizeFileName, sanitizePath, sanitizeUrl, sanitizeText, isValidStripeId, sanitizeStripeCustomerId, sanitizeStripeSubscriptionId, sanitizeStripePriceId, sanitizeStripeInvoiceId, sanitizeStripeEventId, } from './sanitization.js';
|
|
13
15
|
export { validateDbPath, validateDbPathOrThrow, isPathSafe, DEFAULT_ALLOWED_DIRS, } from './pathValidation.js';
|
|
14
16
|
export type { PathValidationOptions, PathValidationResult } from './pathValidation.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAI3B,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EAEZ,eAAe,EACf,wBAAwB,EACxB,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,UAAU,EACV,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAGtF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,YAAY,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,GACX,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,kBAAkB,EAClB,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,yBAAyB,CAAA;AAChC,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGtD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACtF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
*/
|
|
10
10
|
// Scanner module
|
|
11
11
|
export { SecurityScanner } from './scanner/index.js';
|
|
12
|
+
// SMI-5535 R0 Wave 2A: the hostile-update (rug-pull) comparator is a public
|
|
13
|
+
// feature; surface it (+ its default threshold + verdict type) through the
|
|
14
|
+
// security barrel so it is reachable from `@skillsmith/core`.
|
|
15
|
+
export { compareScanReports, DEFAULT_RISK_THRESHOLD } from './scanner/index.js';
|
|
12
16
|
// Sanitization
|
|
13
17
|
export { sanitizeHtml, sanitizeFileName, sanitizePath, sanitizeUrl, sanitizeText,
|
|
14
18
|
// SMI-1062: Stripe ID validators
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iBAAiB;AACjB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iBAAiB;AACjB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AASpD,4EAA4E;AAC5E,2EAA2E;AAC3E,8DAA8D;AAC9D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAG/E,eAAe;AACf,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY;AACZ,iCAAiC;AACjC,eAAe,EACf,wBAAwB,EACxB,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAE1B,kBAAkB;AAClB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,UAAU,EACV,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAG5B,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAU9C,sBAAsB;AACtB,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,kBAAkB,EAClB,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,yBAAyB,CAAA;AAQhC,iCAAiC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGjD,0CAA0C;AAC1C,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Scanner — compound chmod+fetch signal detector
|
|
3
|
+
* @module @skillsmith/core/security/scanner/SecurityScanner.compound
|
|
4
|
+
*
|
|
5
|
+
* SMI-5434: Section 2 of SecurityScanner.scanners.ts extracted so that the
|
|
6
|
+
* upcoming SMI-5433 regex widening (~40 lines) can land without breaching the
|
|
7
|
+
* 500-line audit:standards gate. Pure functions of (content, alreadyFlaggedLines,
|
|
8
|
+
* lineContexts) — no scanner instance state.
|
|
9
|
+
*/
|
|
10
|
+
import type { SecurityFinding } from './types.js';
|
|
11
|
+
import type { LineContext } from './SecurityScanner.helpers.js';
|
|
12
|
+
export declare function scanChmodFetchCompound(content: string, alreadyFlaggedLines: ReadonlySet<number>, lineContexts?: LineContext[]): SecurityFinding[];
|
|
13
|
+
//# sourceMappingURL=SecurityScanner.compound.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecurityScanner.compound.d.ts","sourceRoot":"","sources":["../../../../src/security/scanner/SecurityScanner.compound.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAiE/D,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,EACxC,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,eAAe,EAAE,CAyDnB"}
|