@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
|
@@ -10,19 +10,40 @@
|
|
|
10
10
|
* mutation) so arrow-const exports can be wrapped without mutation.
|
|
11
11
|
* Applied review change H4: `framework` is captured per-call, not memoised.
|
|
12
12
|
*/
|
|
13
|
+
import type { AgentMarker } from './agent-marker.js';
|
|
13
14
|
type AnyFunction = (...args: never[]) => unknown;
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* Run `fn` with `enabled` installed as the emission-gate decision for every
|
|
17
|
+
* telemetry emit inside its async continuation. Concurrency-safe: parallel
|
|
18
|
+
* invocations each see only their own value; code outside any
|
|
19
|
+
* `runWithEmissionGate` scope falls back to the module `let` (default-suppress
|
|
20
|
+
* when that too is unset).
|
|
16
21
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
22
|
+
* Takes a resolved boolean VALUE (consent resolved once at dispatch) — contrast
|
|
23
|
+
* `setEmissionGate`, which takes a predicate thunk. The value is read live in
|
|
24
|
+
* the emit path, so an in-flight call always observes the gate active for ITS
|
|
25
|
+
* OWN scope, never a sibling's.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runWithEmissionGate<T>(enabled: boolean, fn: () => Promise<T>): Promise<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Install (or clear) the process-wide FALLBACK emission gate.
|
|
21
30
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
31
|
+
* @deprecated Prefer `runWithEmissionGate`, which scopes the decision to a
|
|
32
|
+
* single call's async continuation and auto-unwinds — no reset discipline, no
|
|
33
|
+
* cross-call leak. `setEmissionGate` survives only as a test seam and the
|
|
34
|
+
* pre-SMI-5479 fallback: its predicate is consulted (evaluated once per wrapped
|
|
35
|
+
* call, in the `finally` block) ONLY when no `runWithEmissionGate` scope is
|
|
36
|
+
* active. Pass a predicate to enable emission when it returns true; pass
|
|
37
|
+
* `undefined` to revert to default-suppress.
|
|
24
38
|
*/
|
|
25
39
|
export declare function setEmissionGate(gate: (() => boolean) | undefined): void;
|
|
40
|
+
/**
|
|
41
|
+
* Run `fn` with `marker` installed as the agent-mediation context for every
|
|
42
|
+
* telemetry emit inside its async continuation. Concurrency-safe: parallel
|
|
43
|
+
* invocations each see only their own marker; code outside any
|
|
44
|
+
* `runWithMarkerContext` scope sees no marker (fields default false/false/null).
|
|
45
|
+
*/
|
|
46
|
+
export declare function runWithMarkerContext<T>(marker: AgentMarker, fn: () => Promise<T>): Promise<T>;
|
|
26
47
|
/**
|
|
27
48
|
* Options for `withTelemetry`.
|
|
28
49
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../../src/telemetry/wrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../../src/telemetry/wrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAWpD,KAAK,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAA;AAwChD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEzF;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAEvE;AAsBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAE7F;AAmCD;;;;;;GAMG;AAMH,MAAM,WAAW,iBAAiB,CAAC,KAAK,SAAS,SAAS,OAAO,EAAE;IACjE,8EAA8E;IAC9E,MAAM,EAAE,UAAU,GAAG,KAAK,GAAG,kBAAkB,CAAA;IAC/C,qEAAqE;IACrE,cAAc,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAA;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAA;CAC3C;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,KAAK,SAAS,SAAS,OAAO,EAAE,EAAE,OAAO,EACrE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,EACvD,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAC7B,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CA0FtC;AAMD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAEtD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-5479: `runWithEmissionGate` (AsyncLocalStorage emission gate) unit +
|
|
3
|
+
* concurrency coverage. Sibling to `wrap.test.ts` (split per the 500-line file
|
|
4
|
+
* gate); the pre-SMI-5479 module-`let` emission-gate cases stay in
|
|
5
|
+
* `wrap.test.ts` §9 untouched, proving the retained fallback's zero churn.
|
|
6
|
+
*
|
|
7
|
+
* Covers:
|
|
8
|
+
* - T5: `runWithEmissionGate` unit — basic emit/suppress, nested scopes
|
|
9
|
+
* (inner shadows outer), auto-unwind on return AND on throw,
|
|
10
|
+
* ALS-store-beats-module-`let` precedence, fallback to the module `let`
|
|
11
|
+
* when no store is present, and the false-shadow pin
|
|
12
|
+
* (`setEmissionGate(() => true)` + active `runWithEmissionGate(false, …)`
|
|
13
|
+
* → zero emit — pins `??` vs `||` at the emit read; an accidental `||`
|
|
14
|
+
* would leak emission from a consent-off call).
|
|
15
|
+
* - T3: parallel no-bleed for the GATE (P-5 heart) — manually-resolved
|
|
16
|
+
* promises interleave one scope's exit against an in-flight call in another
|
|
17
|
+
* scope; the in-flight call still emits per ITS OWN scope. The committed
|
|
18
|
+
* regression pin for the `wrap.ts` ALS-precedence read — it fails if that
|
|
19
|
+
* read is ever reverted to consult the module `let` only.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=wrap.gate.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.gate.test.d.ts","sourceRoot":"","sources":["../../../src/telemetry/wrap.gate.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-5479: `runWithEmissionGate` (AsyncLocalStorage emission gate) unit +
|
|
3
|
+
* concurrency coverage. Sibling to `wrap.test.ts` (split per the 500-line file
|
|
4
|
+
* gate); the pre-SMI-5479 module-`let` emission-gate cases stay in
|
|
5
|
+
* `wrap.test.ts` §9 untouched, proving the retained fallback's zero churn.
|
|
6
|
+
*
|
|
7
|
+
* Covers:
|
|
8
|
+
* - T5: `runWithEmissionGate` unit — basic emit/suppress, nested scopes
|
|
9
|
+
* (inner shadows outer), auto-unwind on return AND on throw,
|
|
10
|
+
* ALS-store-beats-module-`let` precedence, fallback to the module `let`
|
|
11
|
+
* when no store is present, and the false-shadow pin
|
|
12
|
+
* (`setEmissionGate(() => true)` + active `runWithEmissionGate(false, …)`
|
|
13
|
+
* → zero emit — pins `??` vs `||` at the emit read; an accidental `||`
|
|
14
|
+
* would leak emission from a consent-off call).
|
|
15
|
+
* - T3: parallel no-bleed for the GATE (P-5 heart) — manually-resolved
|
|
16
|
+
* promises interleave one scope's exit against an in-flight call in another
|
|
17
|
+
* scope; the in-flight call still emits per ITS OWN scope. The committed
|
|
18
|
+
* regression pin for the `wrap.ts` ALS-precedence read — it fails if that
|
|
19
|
+
* read is ever reverted to consult the module `let` only.
|
|
20
|
+
*/
|
|
21
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
22
|
+
import { withTelemetry, setEmissionGate, runWithEmissionGate } from './wrap.js';
|
|
23
|
+
vi.mock('./posthog.js', () => ({
|
|
24
|
+
trackSkillInvoke: vi.fn(),
|
|
25
|
+
}));
|
|
26
|
+
// SMI-5615: test seam for the Wave-2 `logging/redact.ts` module — see
|
|
27
|
+
// wrap.test.ts for rationale.
|
|
28
|
+
vi.mock('../logging/redact.js', () => ({
|
|
29
|
+
redactSensitiveData: (s) => s,
|
|
30
|
+
}));
|
|
31
|
+
import { trackSkillInvoke } from './posthog.js';
|
|
32
|
+
const mockTrack = vi.mocked(trackSkillInvoke);
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
mockTrack.mockReset();
|
|
35
|
+
// No module `let` gate by default — the ALS scope is the unit under test.
|
|
36
|
+
// Cases that exercise the fallback / false-shadow install one explicitly.
|
|
37
|
+
setEmissionGate(undefined);
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
setEmissionGate(undefined);
|
|
41
|
+
// The ALS gate needs no reset — `runWithEmissionGate` auto-scopes to its
|
|
42
|
+
// callback, so nothing can leak across tests.
|
|
43
|
+
});
|
|
44
|
+
const BASE_OPTS = {
|
|
45
|
+
source: 'mcp-tool',
|
|
46
|
+
extractSkillId: () => 'test/skill',
|
|
47
|
+
};
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// T5 — runWithEmissionGate unit
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
describe('runWithEmissionGate (T5 — ALS emission gate)', () => {
|
|
52
|
+
it('emits inside a runWithEmissionGate(true) scope', async () => {
|
|
53
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
54
|
+
await runWithEmissionGate(true, () => wrapped());
|
|
55
|
+
expect(mockTrack).toHaveBeenCalledOnce();
|
|
56
|
+
});
|
|
57
|
+
it('suppresses inside a runWithEmissionGate(false) scope', async () => {
|
|
58
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
59
|
+
await runWithEmissionGate(false, () => wrapped());
|
|
60
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
61
|
+
});
|
|
62
|
+
it('nested scopes — inner false shadows outer true (no emit)', async () => {
|
|
63
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
64
|
+
await runWithEmissionGate(true, () => runWithEmissionGate(false, () => wrapped()));
|
|
65
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
66
|
+
});
|
|
67
|
+
it('nested scopes — inner true shadows outer false (emit)', async () => {
|
|
68
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
69
|
+
await runWithEmissionGate(false, () => runWithEmissionGate(true, () => wrapped()));
|
|
70
|
+
expect(mockTrack).toHaveBeenCalledOnce();
|
|
71
|
+
});
|
|
72
|
+
it('auto-unwinds on return — a call after the scope resolves falls back to default-suppress', async () => {
|
|
73
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
74
|
+
await runWithEmissionGate(true, () => wrapped());
|
|
75
|
+
expect(mockTrack).toHaveBeenCalledOnce();
|
|
76
|
+
mockTrack.mockReset();
|
|
77
|
+
// Outside the scope now — no module gate installed → default-suppress.
|
|
78
|
+
await wrapped();
|
|
79
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
it('auto-unwinds on throw — the scope does not leak to a later out-of-scope call', async () => {
|
|
82
|
+
const boom = withTelemetry(() => {
|
|
83
|
+
throw new Error('handler exploded');
|
|
84
|
+
}, BASE_OPTS);
|
|
85
|
+
await expect(runWithEmissionGate(true, () => boom())).rejects.toThrow('handler exploded');
|
|
86
|
+
// The throwing call itself emits (success:false) — the `finally` runs inside
|
|
87
|
+
// the still-live scope.
|
|
88
|
+
expect(mockTrack).toHaveBeenCalledOnce();
|
|
89
|
+
expect(mockTrack).toHaveBeenCalledWith(expect.objectContaining({ success: false }));
|
|
90
|
+
mockTrack.mockReset();
|
|
91
|
+
// The scope has unwound — a later out-of-scope call must not inherit `true`.
|
|
92
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
93
|
+
await wrapped();
|
|
94
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
95
|
+
});
|
|
96
|
+
it('ALS store beats the module `let` — store true wins over a module-`let` false', async () => {
|
|
97
|
+
setEmissionGate(() => false);
|
|
98
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
99
|
+
await runWithEmissionGate(true, () => wrapped());
|
|
100
|
+
expect(mockTrack).toHaveBeenCalledOnce();
|
|
101
|
+
});
|
|
102
|
+
it('false-shadow pin (`??` not `||`) — store false wins over a permissive module `let`', async () => {
|
|
103
|
+
// The heart of the `??` vs `||` pin: a permissive module gate is installed,
|
|
104
|
+
// but an active consent-OFF ALS scope must suppress. `||` would let the
|
|
105
|
+
// module `true` leak emission from a consent-off call.
|
|
106
|
+
setEmissionGate(() => true);
|
|
107
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
108
|
+
await runWithEmissionGate(false, () => wrapped());
|
|
109
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
110
|
+
});
|
|
111
|
+
it('falls back to the module `let` when no ALS scope is present (thunk true → emit)', async () => {
|
|
112
|
+
setEmissionGate(() => true);
|
|
113
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
114
|
+
await wrapped();
|
|
115
|
+
expect(mockTrack).toHaveBeenCalledOnce();
|
|
116
|
+
});
|
|
117
|
+
it('falls back to the module `let` when no ALS scope is present (thunk false → no emit)', async () => {
|
|
118
|
+
setEmissionGate(() => false);
|
|
119
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
120
|
+
await wrapped();
|
|
121
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
122
|
+
});
|
|
123
|
+
it('default-suppress — no ALS scope and no module gate → no emit', async () => {
|
|
124
|
+
const wrapped = withTelemetry(() => 'ok', BASE_OPTS);
|
|
125
|
+
await wrapped();
|
|
126
|
+
expect(mockTrack).not.toHaveBeenCalled();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// T3 — parallel no-bleed for the GATE (P-5 heart; committed regression pin)
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
describe('parallel no-bleed for the emission gate (T3 — P-5 invariant)', () => {
|
|
133
|
+
it('concurrent calls in different gate scopes each emit per their OWN scope', async () => {
|
|
134
|
+
// Failure mode this guards: if the emit read ignored the ALS store (a
|
|
135
|
+
// revert of the `wrap.ts` precedence read to the module `let` only), a
|
|
136
|
+
// consent-ON call's emit would be governed by whatever shared state last
|
|
137
|
+
// held — here call A's consent-OFF scope exiting mid-flight of B. Force the
|
|
138
|
+
// interleaving with manually-resolved promises: A (gate OFF) and B (gate
|
|
139
|
+
// ON) both start; A finishes (and must NOT emit) while B is still awaiting;
|
|
140
|
+
// then B finishes and MUST still emit per its own ON scope.
|
|
141
|
+
let releaseA;
|
|
142
|
+
let releaseB;
|
|
143
|
+
const blockA = new Promise((r) => (releaseA = r));
|
|
144
|
+
const blockB = new Promise((r) => (releaseB = r));
|
|
145
|
+
const emitted = [];
|
|
146
|
+
mockTrack.mockImplementation((p) => {
|
|
147
|
+
emitted.push(p.skillId);
|
|
148
|
+
});
|
|
149
|
+
const wrappedA = withTelemetry(async () => {
|
|
150
|
+
await blockA;
|
|
151
|
+
return 'A';
|
|
152
|
+
}, { ...BASE_OPTS, extractSkillId: () => 'tool-a' });
|
|
153
|
+
const wrappedB = withTelemetry(async () => {
|
|
154
|
+
await blockB;
|
|
155
|
+
return 'B';
|
|
156
|
+
}, { ...BASE_OPTS, extractSkillId: () => 'tool-b' });
|
|
157
|
+
// A in a consent-OFF scope, B in a consent-ON scope, both in flight.
|
|
158
|
+
const callA = runWithEmissionGate(false, () => wrappedA());
|
|
159
|
+
const callB = runWithEmissionGate(true, () => wrappedB());
|
|
160
|
+
// A completes (its `finally` runs inside A's OFF scope) while B still awaits.
|
|
161
|
+
releaseA();
|
|
162
|
+
await callA;
|
|
163
|
+
expect(emitted).toEqual([]); // A suppressed correctly; B not yet emitted.
|
|
164
|
+
// B completes — its emit reads B's OWN ON scope, not A's exited OFF scope.
|
|
165
|
+
releaseB();
|
|
166
|
+
await callB;
|
|
167
|
+
expect(emitted).toEqual(['tool-b']);
|
|
168
|
+
});
|
|
169
|
+
it('a sibling ON call still emits after a nested (middleware-style) ON scope unwinds', async () => {
|
|
170
|
+
// Models the double-gate reconciliation (Steps 2-3): an outer dispatch
|
|
171
|
+
// scope (ON) drives call X through a NESTED runWithEmissionGate (the
|
|
172
|
+
// middleware's own scope) that resolves and auto-unwinds first, while a
|
|
173
|
+
// sibling direct-dispatch call Y (ON) is still in flight. Y's emit must
|
|
174
|
+
// still fire — the inner scope's exit must not disturb Y's own scope.
|
|
175
|
+
let releaseX;
|
|
176
|
+
let releaseY;
|
|
177
|
+
const blockX = new Promise((r) => (releaseX = r));
|
|
178
|
+
const blockY = new Promise((r) => (releaseY = r));
|
|
179
|
+
const emitted = [];
|
|
180
|
+
mockTrack.mockImplementation((p) => {
|
|
181
|
+
emitted.push(p.skillId);
|
|
182
|
+
});
|
|
183
|
+
const wrappedX = withTelemetry(async () => {
|
|
184
|
+
await blockX;
|
|
185
|
+
return 'X';
|
|
186
|
+
}, { ...BASE_OPTS, extractSkillId: () => 'tool-x' });
|
|
187
|
+
const wrappedY = withTelemetry(async () => {
|
|
188
|
+
await blockY;
|
|
189
|
+
return 'Y';
|
|
190
|
+
}, { ...BASE_OPTS, extractSkillId: () => 'tool-y' });
|
|
191
|
+
// X: a nested ON scope inside an ON dispatch scope (the double-gate shape).
|
|
192
|
+
const callX = runWithEmissionGate(true, () => runWithEmissionGate(true, () => wrappedX()));
|
|
193
|
+
// Y: a sibling direct-dispatch ON scope, in flight.
|
|
194
|
+
const callY = runWithEmissionGate(true, () => wrappedY());
|
|
195
|
+
releaseX();
|
|
196
|
+
await callX;
|
|
197
|
+
releaseY();
|
|
198
|
+
await callY;
|
|
199
|
+
expect(emitted).toEqual(['tool-x', 'tool-y']);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
//# sourceMappingURL=wrap.gate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.gate.test.js","sourceRoot":"","sources":["../../../src/telemetry/wrap.gate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,43 +10,137 @@
|
|
|
10
10
|
* mutation) so arrow-const exports can be wrapped without mutation.
|
|
11
11
|
* Applied review change H4: `framework` is captured per-call, not memoised.
|
|
12
12
|
*/
|
|
13
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
14
|
+
import { randomUUID } from 'node:crypto';
|
|
13
15
|
import { trackSkillInvoke } from './posthog.js';
|
|
16
|
+
import { getCorrelationId, runWithCorrelationId } from '../logging/context.js';
|
|
17
|
+
import { redactSensitiveData } from '../logging/redact.js';
|
|
14
18
|
const wrapped = new Set();
|
|
15
19
|
// ---------------------------------------------------------------------------
|
|
16
|
-
// Emission gate (SMI-5019 wire-in)
|
|
20
|
+
// Emission gate (SMI-5019 wire-in; SMI-5479 AsyncLocalStorage refactor)
|
|
17
21
|
// ---------------------------------------------------------------------------
|
|
18
22
|
//
|
|
19
|
-
// Default-suppress: until an emission gate is
|
|
20
|
-
//
|
|
21
|
-
// (e.g. the mcp-server license-gate middleware) MUST call `setEmissionGate`
|
|
22
|
-
// during request handling to enable emission for their context.
|
|
23
|
-
//
|
|
24
|
-
// The alternative (default-emit) would be backwards-compatible but risks
|
|
23
|
+
// Default-suppress: until an emission gate is active, `withTelemetry` does NOT
|
|
24
|
+
// emit. Privacy-safe by construction — the alternative (default-emit) risks
|
|
25
25
|
// emitting telemetry for an unknown anonymous_id before consent has been
|
|
26
|
-
// resolved. We pick the privacy-safe default per SMI-5019; a misconfigured
|
|
27
|
-
//
|
|
28
|
-
//
|
|
26
|
+
// resolved. We pick the privacy-safe default per SMI-5019; a misconfigured host
|
|
27
|
+
// that never opens a gate simply emits no telemetry, which is observable
|
|
28
|
+
// (counts stay at zero) and recoverable.
|
|
29
29
|
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
30
|
+
// Two gates feed the emit-path read (in the `finally` block below), in
|
|
31
|
+
// precedence order:
|
|
32
|
+
//
|
|
33
|
+
// 1. `emissionGateStorage` (PRIMARY) — an `AsyncLocalStorage<boolean>`
|
|
34
|
+
// scoped per tool call via `runWithEmissionGate`. New call sites (the
|
|
35
|
+
// mcp-server dispatch handler + license-gate middleware) resolve consent
|
|
36
|
+
// ONCE at dispatch and pass that resolved VALUE into the scope; the store
|
|
37
|
+
// then governs every emit for the whole of that call's async
|
|
38
|
+
// continuation. Mirrors the marker-context ALS below one-for-one — the
|
|
39
|
+
// reason nested / concurrent installs are safe: `.run()` is reentrant and
|
|
40
|
+
// each async continuation is isolated, so a sibling call can never observe
|
|
41
|
+
// or clear this call's gate.
|
|
42
|
+
// 2. `emissionGate` (FALLBACK) — a process-wide module `let`, a THUNK
|
|
43
|
+
// installed via `setEmissionGate`, consulted only when no ALS store is
|
|
44
|
+
// present. Retained solely as a test seam and a deprecated fallback for
|
|
45
|
+
// the pre-SMI-5479 shape; new production code MUST use
|
|
46
|
+
// `runWithEmissionGate`.
|
|
47
|
+
//
|
|
48
|
+
// Multi-tenancy caveat (RESOLVED by SMI-5479): the gate used to be purely
|
|
49
|
+
// module-scoped, which a future multi-tenant transport could not share safely.
|
|
50
|
+
// The `AsyncLocalStorage`-backed per-request state that caveat deferred is now
|
|
51
|
+
// applied here — per-call scope isolates concurrent consents. See the matching
|
|
52
|
+
// note in `license.gate.ts`.
|
|
53
|
+
const emissionGateStorage = new AsyncLocalStorage();
|
|
35
54
|
/**
|
|
36
|
-
*
|
|
55
|
+
* Run `fn` with `enabled` installed as the emission-gate decision for every
|
|
56
|
+
* telemetry emit inside its async continuation. Concurrency-safe: parallel
|
|
57
|
+
* invocations each see only their own value; code outside any
|
|
58
|
+
* `runWithEmissionGate` scope falls back to the module `let` (default-suppress
|
|
59
|
+
* when that too is unset).
|
|
37
60
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
61
|
+
* Takes a resolved boolean VALUE (consent resolved once at dispatch) — contrast
|
|
62
|
+
* `setEmissionGate`, which takes a predicate thunk. The value is read live in
|
|
63
|
+
* the emit path, so an in-flight call always observes the gate active for ITS
|
|
64
|
+
* OWN scope, never a sibling's.
|
|
65
|
+
*/
|
|
66
|
+
export function runWithEmissionGate(enabled, fn) {
|
|
67
|
+
return emissionGateStorage.run(enabled, fn);
|
|
68
|
+
}
|
|
69
|
+
// Process-wide FALLBACK gate — a module `let` thunk (test-only / deprecated).
|
|
70
|
+
// Superseded by `runWithEmissionGate`; retained so existing unit tests and any
|
|
71
|
+
// pre-SMI-5479 caller keep working with zero churn.
|
|
72
|
+
let emissionGate;
|
|
73
|
+
/**
|
|
74
|
+
* Install (or clear) the process-wide FALLBACK emission gate.
|
|
42
75
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
76
|
+
* @deprecated Prefer `runWithEmissionGate`, which scopes the decision to a
|
|
77
|
+
* single call's async continuation and auto-unwinds — no reset discipline, no
|
|
78
|
+
* cross-call leak. `setEmissionGate` survives only as a test seam and the
|
|
79
|
+
* pre-SMI-5479 fallback: its predicate is consulted (evaluated once per wrapped
|
|
80
|
+
* call, in the `finally` block) ONLY when no `runWithEmissionGate` scope is
|
|
81
|
+
* active. Pass a predicate to enable emission when it returns true; pass
|
|
82
|
+
* `undefined` to revert to default-suppress.
|
|
45
83
|
*/
|
|
46
84
|
export function setEmissionGate(gate) {
|
|
47
85
|
emissionGate = gate;
|
|
48
86
|
}
|
|
49
87
|
// ---------------------------------------------------------------------------
|
|
88
|
+
// Agent-mediation marker context (SMI-5456)
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
//
|
|
91
|
+
// The three per-event marker fields (`agent_session`, `nudge_origin`,
|
|
92
|
+
// `trigger_id`) do not live in the handler's arguments — they arrive on the MCP
|
|
93
|
+
// request's `_meta` or a session marker file, both resolved by the dispatch
|
|
94
|
+
// layer. The dispatcher runs each dispatch inside `runWithMarkerContext` and
|
|
95
|
+
// `withTelemetry` reads the store live in its emit path — never memoised,
|
|
96
|
+
// mirroring the per-call `framework` capture (H4).
|
|
97
|
+
//
|
|
98
|
+
// `AsyncLocalStorage` (not a module-scoped variable) because harnesses batch
|
|
99
|
+
// PARALLEL tool calls to one server process (Claude Code emits multiple
|
|
100
|
+
// tool_use blocks in one response). A module-scoped slot would let call A's
|
|
101
|
+
// completion clear call B's still-in-flight marker — silently zeroing
|
|
102
|
+
// `agent_session` on genuinely mediated calls and undercounting the mediation
|
|
103
|
+
// gate metric. ALS scopes the marker to each call's own async continuation, so
|
|
104
|
+
// concurrent calls cannot observe or clear each other's context.
|
|
105
|
+
const markerStorage = new AsyncLocalStorage();
|
|
106
|
+
/**
|
|
107
|
+
* Run `fn` with `marker` installed as the agent-mediation context for every
|
|
108
|
+
* telemetry emit inside its async continuation. Concurrency-safe: parallel
|
|
109
|
+
* invocations each see only their own marker; code outside any
|
|
110
|
+
* `runWithMarkerContext` scope sees no marker (fields default false/false/null).
|
|
111
|
+
*/
|
|
112
|
+
export function runWithMarkerContext(marker, fn) {
|
|
113
|
+
return markerStorage.run(marker, fn);
|
|
114
|
+
}
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Error capture (SMI-5615)
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
//
|
|
119
|
+
// `trackSkillInvoke` previously reported only `success: boolean` on failure —
|
|
120
|
+
// the caught error was discarded entirely. No stack traces leave the machine:
|
|
121
|
+
// only the error's class name and a redacted, truncated message ride the
|
|
122
|
+
// already-consent-gated `skill_invoke` event.
|
|
123
|
+
const MAX_ERROR_MESSAGE_LENGTH = 256;
|
|
124
|
+
/** Extract a best-effort string message from an unknown caught value. */
|
|
125
|
+
function errorMessageOf(e) {
|
|
126
|
+
if (e instanceof Error)
|
|
127
|
+
return e.message;
|
|
128
|
+
if (typeof e === 'string')
|
|
129
|
+
return e;
|
|
130
|
+
try {
|
|
131
|
+
return JSON.stringify(e);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return String(e);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Truncate a (already redacted) error message to `MAX_ERROR_MESSAGE_LENGTH`. */
|
|
138
|
+
function truncateErrorMessage(message) {
|
|
139
|
+
return message.length > MAX_ERROR_MESSAGE_LENGTH
|
|
140
|
+
? message.slice(0, MAX_ERROR_MESSAGE_LENGTH)
|
|
141
|
+
: message;
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
50
144
|
// HOF
|
|
51
145
|
// ---------------------------------------------------------------------------
|
|
52
146
|
/**
|
|
@@ -69,39 +163,89 @@ export function setEmissionGate(gate) {
|
|
|
69
163
|
*/
|
|
70
164
|
export function withTelemetry(handler, opts) {
|
|
71
165
|
const wrappedFn = async (...args) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
166
|
+
// SMI-5615 (F1 fix, corrected from the naive design): the correlation-ID
|
|
167
|
+
// scope wraps the ENTIRE body below — try *and* finally — not just the
|
|
168
|
+
// `handler(...args)` call. Installing it around only the handler would
|
|
169
|
+
// leave the finally block's emit path outside the ALS scope, so the
|
|
170
|
+
// `getCorrelationId()` read there would always see `undefined`, silently
|
|
171
|
+
// defeating the feature. Mint-if-absent (`getCorrelationId() ?? randomUUID()`)
|
|
172
|
+
// means a wrapped call nested inside another wrapped call's continuation
|
|
173
|
+
// inherits the outer ID instead of fragmenting one logical request's trace.
|
|
174
|
+
return runWithCorrelationId(getCorrelationId() ?? randomUUID(), async () => {
|
|
175
|
+
const start = Date.now();
|
|
176
|
+
const skillId = opts.extractSkillId(args);
|
|
177
|
+
// Per H4: evaluated per-call so a single server process can serve multiple
|
|
178
|
+
// clients with different frameworks on the same HTTP transport.
|
|
179
|
+
const framework = opts.extractFramework?.(args) ?? 'unknown';
|
|
180
|
+
let success = true;
|
|
181
|
+
let caughtError;
|
|
88
182
|
try {
|
|
89
|
-
|
|
90
|
-
// no gate is installed — see module-level comment for the rationale.
|
|
91
|
-
if (emissionGate && emissionGate()) {
|
|
92
|
-
trackSkillInvoke({
|
|
93
|
-
skillId,
|
|
94
|
-
source: opts.source,
|
|
95
|
-
framework,
|
|
96
|
-
durationMs: Date.now() - start,
|
|
97
|
-
success,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
183
|
+
return await handler(...args);
|
|
100
184
|
}
|
|
101
|
-
catch {
|
|
102
|
-
|
|
185
|
+
catch (e) {
|
|
186
|
+
success = false;
|
|
187
|
+
caughtError = e;
|
|
188
|
+
throw e;
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
// Emit BEFORE the catch re-throw lands; swallow telemetry errors so they
|
|
192
|
+
// never affect the wrapped function's observable behaviour.
|
|
193
|
+
try {
|
|
194
|
+
// SMI-5019 wire-in / SMI-5479 refactor: consult the emission gate. The
|
|
195
|
+
// per-call ALS store (PRIMARY) wins over the module `let` thunk
|
|
196
|
+
// (FALLBACK). `??` — not `||` — so an ALS `false` suppresses even when a
|
|
197
|
+
// permissive module gate is installed: a consent-off scope must never
|
|
198
|
+
// leak emission. Default-suppress holds when neither is present (no
|
|
199
|
+
// store + no thunk → `undefined` → no emit).
|
|
200
|
+
const gateOn = emissionGateStorage.getStore() ?? (emissionGate ? emissionGate() : undefined);
|
|
201
|
+
if (gateOn) {
|
|
202
|
+
// SMI-5456: thread the marker from this call's ALS scope into the
|
|
203
|
+
// event. Read here (not memoised) so it reflects the marker installed
|
|
204
|
+
// for THIS call's async continuation — concurrent calls each see
|
|
205
|
+
// their own. Consent parity is automatic — these fields only ride an
|
|
206
|
+
// event that the emission gate already permitted.
|
|
207
|
+
const marker = markerStorage.getStore();
|
|
208
|
+
trackSkillInvoke({
|
|
209
|
+
skillId,
|
|
210
|
+
source: opts.source,
|
|
211
|
+
// Per-harness attribution: the marker channel's vocabulary-validated
|
|
212
|
+
// `harness` wins over the extractor result — every MCP-tool call
|
|
213
|
+
// site hardcodes `extractFramework: () => 'unknown'`, so without
|
|
214
|
+
// this the per-harness split never survives to the wire. H4
|
|
215
|
+
// (per-call, never memoised) is preserved: the ALS store IS
|
|
216
|
+
// per-request state, read here on every emit. CLI / VS Code
|
|
217
|
+
// callers never install marker context, so `getStore()` is
|
|
218
|
+
// undefined there and their real extractors keep winning.
|
|
219
|
+
framework: marker?.harness ?? framework,
|
|
220
|
+
durationMs: Date.now() - start,
|
|
221
|
+
success,
|
|
222
|
+
agentSession: marker?.agentSession ?? false,
|
|
223
|
+
nudgeOrigin: marker?.nudgeOrigin ?? false,
|
|
224
|
+
triggerId: marker?.triggerId ?? null,
|
|
225
|
+
// SMI-5615: cross-signal join key — a disk log line, an OTel span,
|
|
226
|
+
// and this PostHog event for one failure share this ID. Read live
|
|
227
|
+
// from the still-open scope established above (F1 fix), always
|
|
228
|
+
// present regardless of success/failure.
|
|
229
|
+
correlationId: getCorrelationId(),
|
|
230
|
+
// SMI-5615: capture the previously-discarded error on failure only.
|
|
231
|
+
// No stack traces leave the machine — class name + redacted,
|
|
232
|
+
// truncated (<=256 char) message only.
|
|
233
|
+
...(success
|
|
234
|
+
? {}
|
|
235
|
+
: {
|
|
236
|
+
errorName: caughtError instanceof Error
|
|
237
|
+
? caughtError.constructor.name
|
|
238
|
+
: typeof caughtError,
|
|
239
|
+
errorMessage: truncateErrorMessage(redactSensitiveData(errorMessageOf(caughtError))),
|
|
240
|
+
}),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// Intentionally swallowed — telemetry must never break user code.
|
|
246
|
+
}
|
|
103
247
|
}
|
|
104
|
-
}
|
|
248
|
+
});
|
|
105
249
|
};
|
|
106
250
|
wrapped.add(wrappedFn);
|
|
107
251
|
return wrappedFn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../../src/telemetry/wrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../../src/telemetry/wrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-5456: withTelemetry agent-mediation marker threading + Tier-2 framework
|
|
3
|
+
* emission. Sibling to `wrap.test.ts` (split per the 500-line file gate).
|
|
4
|
+
*
|
|
5
|
+
* Covers:
|
|
6
|
+
* - marker context threaded into the emitted payload (via runWithMarkerContext)
|
|
7
|
+
* - defaults false / false / null outside any marker scope
|
|
8
|
+
* - consent parity (suppressed gate emits nothing, marker or not)
|
|
9
|
+
* - concurrent no-bleed (P-5 invariant) — parallel calls each emit their
|
|
10
|
+
* OWN marker; an unscoped call stays neutral while others' scopes are live
|
|
11
|
+
* - per-framework emission incl. the opencode / hermes enum additions
|
|
12
|
+
* - marker `harness` feeds the event's `framework` (single-point per-harness
|
|
13
|
+
* attribution — MCP call sites hardcode `extractFramework: () => 'unknown'`)
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=wrap.marker.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.marker.test.d.ts","sourceRoot":"","sources":["../../../src/telemetry/wrap.marker.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
|