@complior/engine 0.9.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/.well-known/ai-compliance.json +16 -0
- package/COMPLIANCE.md +64 -0
- package/data/data-integrity.test.ts +75 -0
- package/data/eval/eval-mappings.json +33 -0
- package/data/llm/model-pricing.json +15 -0
- package/data/llm/model-routing.json +36 -0
- package/data/onboarding/risk-profile.json +17 -0
- package/data/regulations/eu-ai-act/README.md +245 -0
- package/data/regulations/eu-ai-act/applicability-tree.json +160 -0
- package/data/regulations/eu-ai-act/cross-mapping.json +175 -0
- package/data/regulations/eu-ai-act/localization.json +186 -0
- package/data/regulations/eu-ai-act/obligations.json +3981 -0
- package/data/regulations/eu-ai-act/regulation-meta.json +482 -0
- package/data/regulations/eu-ai-act/scoring.json +342 -0
- package/data/regulations/eu-ai-act/technical-requirements.json +2590 -0
- package/data/regulations/eu-ai-act/timeline.json +160 -0
- package/data/regulations/jurisdictions/at.json +15 -0
- package/data/regulations/jurisdictions/be.json +15 -0
- package/data/regulations/jurisdictions/bg.json +15 -0
- package/data/regulations/jurisdictions/cy.json +15 -0
- package/data/regulations/jurisdictions/cz.json +15 -0
- package/data/regulations/jurisdictions/de.json +15 -0
- package/data/regulations/jurisdictions/dk.json +15 -0
- package/data/regulations/jurisdictions/ee.json +15 -0
- package/data/regulations/jurisdictions/es.json +15 -0
- package/data/regulations/jurisdictions/fi.json +15 -0
- package/data/regulations/jurisdictions/fr.json +15 -0
- package/data/regulations/jurisdictions/gr.json +15 -0
- package/data/regulations/jurisdictions/hr.json +15 -0
- package/data/regulations/jurisdictions/hu.json +15 -0
- package/data/regulations/jurisdictions/ie.json +15 -0
- package/data/regulations/jurisdictions/is.json +15 -0
- package/data/regulations/jurisdictions/it.json +15 -0
- package/data/regulations/jurisdictions/li.json +15 -0
- package/data/regulations/jurisdictions/lt.json +15 -0
- package/data/regulations/jurisdictions/lu.json +15 -0
- package/data/regulations/jurisdictions/lv.json +15 -0
- package/data/regulations/jurisdictions/mt.json +15 -0
- package/data/regulations/jurisdictions/nl.json +15 -0
- package/data/regulations/jurisdictions/no.json +15 -0
- package/data/regulations/jurisdictions/pl.json +15 -0
- package/data/regulations/jurisdictions/pt.json +15 -0
- package/data/regulations/jurisdictions/ro.json +15 -0
- package/data/regulations/jurisdictions/se.json +15 -0
- package/data/regulations/jurisdictions/si.json +15 -0
- package/data/regulations/jurisdictions/sk.json +15 -0
- package/data/scanner/check-id-categories.json +81 -0
- package/data/scanner/confidence-params.json +16 -0
- package/data/scanner/limits.json +4 -0
- package/data/schemas/http-contract-sample.json +79 -0
- package/data/schemas/http-contract.json +144 -0
- package/data/semgrep-rules/bare-call.yaml +37 -0
- package/data/semgrep-rules/injection.yaml +73 -0
- package/data/semgrep-rules/missing-error-handling.yaml +58 -0
- package/data/semgrep-rules/unsafe-deser.yaml +65 -0
- package/data/templates/eu-ai-act/ai-literacy.md +184 -0
- package/data/templates/eu-ai-act/art5-screening.md +131 -0
- package/data/templates/eu-ai-act/data-governance.md +145 -0
- package/data/templates/eu-ai-act/declaration-of-conformity.md +161 -0
- package/data/templates/eu-ai-act/fria.md +127 -0
- package/data/templates/eu-ai-act/gpai-systemic-risk.md +150 -0
- package/data/templates/eu-ai-act/gpai-transparency.md +166 -0
- package/data/templates/eu-ai-act/incident-report.md +188 -0
- package/data/templates/eu-ai-act/instructions-for-use.md +202 -0
- package/data/templates/eu-ai-act/monitoring-policy.md +110 -0
- package/data/templates/eu-ai-act/qms.md +180 -0
- package/data/templates/eu-ai-act/risk-management-system.md +123 -0
- package/data/templates/eu-ai-act/technical-documentation.md +287 -0
- package/data/templates/eu-ai-act/worker-notification.md +143 -0
- package/data/templates/policies/biometrics-ai-policy.md +214 -0
- package/data/templates/policies/critical-infra-ai-policy.md +228 -0
- package/data/templates/policies/education-ai-policy.md +184 -0
- package/data/templates/policies/finance-ai-policy.md +191 -0
- package/data/templates/policies/healthcare-ai-policy.md +197 -0
- package/data/templates/policies/hr-ai-policy.md +178 -0
- package/data/templates/policies/legal-ai-policy.md +189 -0
- package/data/templates/policies/migration-ai-policy.md +239 -0
- package/engine.log +7 -0
- package/package.json +74 -0
- package/src/composition-root.ts +791 -0
- package/src/data/eval/conformity-tests.test.ts +122 -0
- package/src/data/eval/ct-1-transparency.ts +106 -0
- package/src/data/eval/ct-10-gpai.ts +25 -0
- package/src/data/eval/ct-11-industry.ts +42 -0
- package/src/data/eval/ct-2-oversight.ts +41 -0
- package/src/data/eval/ct-3-explanation.ts +14 -0
- package/src/data/eval/ct-4-bias.ts +83 -0
- package/src/data/eval/ct-5-accuracy.ts +41 -0
- package/src/data/eval/ct-6-robustness.ts +81 -0
- package/src/data/eval/ct-7-prohibited.ts +52 -0
- package/src/data/eval/ct-8-logging.ts +68 -0
- package/src/data/eval/ct-9-risk-awareness.ts +33 -0
- package/src/data/eval/deterministic-evaluator.ts +120 -0
- package/src/data/eval/index.ts +55 -0
- package/src/data/eval/judge-prompts.ts +146 -0
- package/src/data/eval/llm-judged-tests.ts +279 -0
- package/src/data/eval/llm-tests.test.ts +83 -0
- package/src/data/eval/remediation/ct-1-transparency.ts +91 -0
- package/src/data/eval/remediation/ct-10-gpai.ts +94 -0
- package/src/data/eval/remediation/ct-11-industry.ts +94 -0
- package/src/data/eval/remediation/ct-2-oversight.ts +71 -0
- package/src/data/eval/remediation/ct-3-explanation.ts +70 -0
- package/src/data/eval/remediation/ct-4-bias.ts +70 -0
- package/src/data/eval/remediation/ct-5-accuracy.ts +70 -0
- package/src/data/eval/remediation/ct-6-robustness.ts +70 -0
- package/src/data/eval/remediation/ct-7-prohibited.ts +94 -0
- package/src/data/eval/remediation/ct-8-logging.ts +94 -0
- package/src/data/eval/remediation/ct-9-risk-awareness.ts +94 -0
- package/src/data/eval/remediation/index.ts +89 -0
- package/src/data/eval/remediation/owasp-art5.ts +15 -0
- package/src/data/eval/remediation/owasp-llm01.ts +72 -0
- package/src/data/eval/remediation/owasp-llm02.ts +72 -0
- package/src/data/eval/remediation/owasp-llm03.ts +15 -0
- package/src/data/eval/remediation/owasp-llm04.ts +15 -0
- package/src/data/eval/remediation/owasp-llm05.ts +15 -0
- package/src/data/eval/remediation/owasp-llm06.ts +15 -0
- package/src/data/eval/remediation/owasp-llm07.ts +15 -0
- package/src/data/eval/remediation/owasp-llm08.ts +15 -0
- package/src/data/eval/remediation/owasp-llm09.ts +15 -0
- package/src/data/eval/remediation/owasp-llm10.ts +15 -0
- package/src/data/eval/remediation/remediation.test.ts +229 -0
- package/src/data/eval/remediation/test-mapping.ts +290 -0
- package/src/data/eval/security-rubrics.ts +381 -0
- package/src/data/finding-explanations.json +453 -0
- package/src/data/industry-patterns.ts +161 -0
- package/src/data/registry-cards.ts +368 -0
- package/src/data/regulation/index.ts +5 -0
- package/src/data/regulation/jurisdiction-data.test.ts +73 -0
- package/src/data/regulation/jurisdiction-data.ts +65 -0
- package/src/data/regulation/regulation-data.ts +19 -0
- package/src/data/regulation/regulation-loader.test.ts +107 -0
- package/src/data/regulation/regulation-loader.ts +56 -0
- package/src/data/scanner-constants.ts +46 -0
- package/src/data/schemas/schemas-core.ts +140 -0
- package/src/data/schemas/schemas-supplementary.ts +211 -0
- package/src/data/schemas/schemas.ts +28 -0
- package/src/data/security/attack-probes.test.ts +62 -0
- package/src/data/security/attack-probes.ts +496 -0
- package/src/data/security/eu-ai-act-security.ts +40 -0
- package/src/data/security/index.ts +19 -0
- package/src/data/security/mitre-atlas.test.ts +43 -0
- package/src/data/security/mitre-atlas.ts +93 -0
- package/src/data/security/nist-ai-rmf.ts +43 -0
- package/src/data/security/owasp-llm-top10.test.ts +60 -0
- package/src/data/security/owasp-llm-top10.ts +138 -0
- package/src/data/template-registry.ts +53 -0
- package/src/data/tool-versions.json +22 -0
- package/src/domain/audit/audit-package.test.ts +152 -0
- package/src/domain/audit/audit-package.ts +166 -0
- package/src/domain/audit/audit-trail.test.ts +121 -0
- package/src/domain/audit/audit-trail.ts +174 -0
- package/src/domain/audit/index.ts +8 -0
- package/src/domain/audit/permissions-matrix.test.ts +136 -0
- package/src/domain/audit/permissions-matrix.ts +121 -0
- package/src/domain/certification/adversarial/bias-tests.ts +95 -0
- package/src/domain/certification/adversarial/evaluators.ts +304 -0
- package/src/domain/certification/adversarial/index.ts +11 -0
- package/src/domain/certification/adversarial/prompt-injection.ts +103 -0
- package/src/domain/certification/adversarial/safety-boundary.ts +132 -0
- package/src/domain/certification/aiuc1-readiness.test.ts +236 -0
- package/src/domain/certification/aiuc1-readiness.ts +298 -0
- package/src/domain/certification/aiuc1-requirements.ts +235 -0
- package/src/domain/certification/index.ts +10 -0
- package/src/domain/certification/redteam-runner.test.ts +97 -0
- package/src/domain/certification/redteam-runner.ts +205 -0
- package/src/domain/certification/test-runner.test.ts +232 -0
- package/src/domain/certification/test-runner.ts +289 -0
- package/src/domain/cost/cost-estimator.test.ts +187 -0
- package/src/domain/cost/cost-estimator.ts +133 -0
- package/src/domain/disclaimer.test.ts +52 -0
- package/src/domain/disclaimer.ts +39 -0
- package/src/domain/documents/ai-enricher.test.ts +120 -0
- package/src/domain/documents/ai-enricher.ts +159 -0
- package/src/domain/documents/document-generator.test.ts +318 -0
- package/src/domain/documents/document-generator.ts +239 -0
- package/src/domain/documents/index.ts +9 -0
- package/src/domain/documents/passport-helpers.ts +25 -0
- package/src/domain/documents/policy-generator.test.ts +252 -0
- package/src/domain/documents/policy-generator.ts +94 -0
- package/src/domain/documents/worker-notification-generator.test.ts +162 -0
- package/src/domain/documents/worker-notification-generator.ts +141 -0
- package/src/domain/eval/adapters/adapter-port.ts +94 -0
- package/src/domain/eval/adapters/adapters.test.ts +303 -0
- package/src/domain/eval/adapters/anthropic-adapter.ts +57 -0
- package/src/domain/eval/adapters/auto-detect.ts +104 -0
- package/src/domain/eval/adapters/create-chat-adapter.ts +106 -0
- package/src/domain/eval/adapters/custom-adapter.ts +74 -0
- package/src/domain/eval/adapters/http-adapter.ts +66 -0
- package/src/domain/eval/adapters/index.ts +7 -0
- package/src/domain/eval/adapters/ollama-adapter.ts +48 -0
- package/src/domain/eval/adapters/openai-adapter.ts +58 -0
- package/src/domain/eval/adapters/with-timeout.ts +25 -0
- package/src/domain/eval/conformity-score.test.ts +161 -0
- package/src/domain/eval/conformity-score.ts +135 -0
- package/src/domain/eval/eval-constants.ts +55 -0
- package/src/domain/eval/eval-evidence.test.ts +85 -0
- package/src/domain/eval/eval-evidence.ts +103 -0
- package/src/domain/eval/eval-fix-generator.test.ts +421 -0
- package/src/domain/eval/eval-fix-generator.ts +205 -0
- package/src/domain/eval/eval-passport.test.ts +82 -0
- package/src/domain/eval/eval-passport.ts +89 -0
- package/src/domain/eval/eval-remediation-report.test.ts +682 -0
- package/src/domain/eval/eval-remediation-report.ts +170 -0
- package/src/domain/eval/eval-report.ts +108 -0
- package/src/domain/eval/eval-runner.test.ts +609 -0
- package/src/domain/eval/eval-runner.ts +593 -0
- package/src/domain/eval/eval-to-findings.test.ts +293 -0
- package/src/domain/eval/eval-to-findings.ts +83 -0
- package/src/domain/eval/index.ts +31 -0
- package/src/domain/eval/llm-judge.test.ts +139 -0
- package/src/domain/eval/llm-judge.ts +168 -0
- package/src/domain/eval/remediation-types.ts +90 -0
- package/src/domain/eval/security-integration.test.ts +196 -0
- package/src/domain/eval/security-integration.ts +136 -0
- package/src/domain/eval/types.test.ts +173 -0
- package/src/domain/eval/types.ts +244 -0
- package/src/domain/eval/verdict-utils.ts +45 -0
- package/src/domain/fixer/create-fixer.ts +101 -0
- package/src/domain/fixer/diff.ts +70 -0
- package/src/domain/fixer/fix-history.ts +23 -0
- package/src/domain/fixer/fixer.test.ts +306 -0
- package/src/domain/fixer/index.ts +9 -0
- package/src/domain/fixer/strategies/bandit-fix.ts +61 -0
- package/src/domain/fixer/strategies/bias-testing.ts +49 -0
- package/src/domain/fixer/strategies/ci-compliance.ts +57 -0
- package/src/domain/fixer/strategies/content-marking.ts +45 -0
- package/src/domain/fixer/strategies/cve-upgrade.ts +66 -0
- package/src/domain/fixer/strategies/data-governance.ts +65 -0
- package/src/domain/fixer/strategies/disclosure.ts +69 -0
- package/src/domain/fixer/strategies/doc-code-sync.ts +53 -0
- package/src/domain/fixer/strategies/documentation.ts +59 -0
- package/src/domain/fixer/strategies/error-handler.ts +63 -0
- package/src/domain/fixer/strategies/hitl-gate.ts +67 -0
- package/src/domain/fixer/strategies/index.ts +61 -0
- package/src/domain/fixer/strategies/kill-switch-test.ts +85 -0
- package/src/domain/fixer/strategies/kill-switch.ts +53 -0
- package/src/domain/fixer/strategies/license-fix.ts +57 -0
- package/src/domain/fixer/strategies/log-retention.ts +40 -0
- package/src/domain/fixer/strategies/logging.ts +59 -0
- package/src/domain/fixer/strategies/metadata.ts +45 -0
- package/src/domain/fixer/strategies/permission-guard.ts +84 -0
- package/src/domain/fixer/strategies/record-keeping.ts +69 -0
- package/src/domain/fixer/strategies/secret-rotation.ts +52 -0
- package/src/domain/fixer/strategies.test.ts +341 -0
- package/src/domain/fixer/template-engine.test.ts +64 -0
- package/src/domain/fixer/template-engine.ts +38 -0
- package/src/domain/fixer/types.ts +88 -0
- package/src/domain/frameworks/aiuc1-framework.test.ts +159 -0
- package/src/domain/frameworks/aiuc1-framework.ts +126 -0
- package/src/domain/frameworks/collect-foundation-metrics.test.ts +96 -0
- package/src/domain/frameworks/collect-foundation-metrics.ts +34 -0
- package/src/domain/frameworks/eu-ai-act-framework.test.ts +117 -0
- package/src/domain/frameworks/eu-ai-act-framework.ts +100 -0
- package/src/domain/frameworks/framework-registry.test.ts +91 -0
- package/src/domain/frameworks/framework-registry.ts +38 -0
- package/src/domain/frameworks/index.ts +8 -0
- package/src/domain/frameworks/mitre-atlas-framework.test.ts +53 -0
- package/src/domain/frameworks/mitre-atlas-framework.ts +53 -0
- package/src/domain/frameworks/owasp-llm-framework.test.ts +77 -0
- package/src/domain/frameworks/owasp-llm-framework.ts +54 -0
- package/src/domain/frameworks/score-plugin-framework.ts +117 -0
- package/src/domain/fria/fria-generator.test.ts +273 -0
- package/src/domain/fria/fria-generator.ts +366 -0
- package/src/domain/import/promptfoo-importer.test.ts +103 -0
- package/src/domain/import/promptfoo-importer.ts +151 -0
- package/src/domain/onboarding/guided-onboarding.test.ts +144 -0
- package/src/domain/onboarding/guided-onboarding.ts +135 -0
- package/src/domain/passport/builder/domain-mapper.ts +9 -0
- package/src/domain/passport/builder/manifest-builder.test.ts +546 -0
- package/src/domain/passport/builder/manifest-builder.ts +535 -0
- package/src/domain/passport/builder/manifest-diff.test.ts +105 -0
- package/src/domain/passport/builder/manifest-diff.ts +89 -0
- package/src/domain/passport/builder/manifest-files.ts +17 -0
- package/src/domain/passport/crypto-signer.test.ts +93 -0
- package/src/domain/passport/crypto-signer.ts +157 -0
- package/src/domain/passport/discovery/agent-discovery.test.ts +296 -0
- package/src/domain/passport/discovery/agent-discovery.ts +325 -0
- package/src/domain/passport/discovery/autonomy-analyzer.test.ts +141 -0
- package/src/domain/passport/discovery/autonomy-analyzer.ts +113 -0
- package/src/domain/passport/discovery/permission-scanner.test.ts +191 -0
- package/src/domain/passport/discovery/permission-scanner.ts +414 -0
- package/src/domain/passport/export/a2a-mapper.ts +75 -0
- package/src/domain/passport/export/aiuc1-mapper.ts +126 -0
- package/src/domain/passport/export/export.test.ts +207 -0
- package/src/domain/passport/export/index.ts +41 -0
- package/src/domain/passport/export/nist-mapper.ts +227 -0
- package/src/domain/passport/import/a2a-importer.test.ts +133 -0
- package/src/domain/passport/import/a2a-importer.ts +156 -0
- package/src/domain/passport/import/index.ts +2 -0
- package/src/domain/passport/index.ts +32 -0
- package/src/domain/passport/obligation-field-map.test.ts +113 -0
- package/src/domain/passport/obligation-field-map.ts +117 -0
- package/src/domain/passport/passport-validator.test.ts +156 -0
- package/src/domain/passport/passport-validator.ts +126 -0
- package/src/domain/passport/scan-to-compliance.test.ts +336 -0
- package/src/domain/passport/scan-to-compliance.ts +166 -0
- package/src/domain/passport/test-generator.test.ts +93 -0
- package/src/domain/passport/test-generator.ts +136 -0
- package/src/domain/proxy/index.ts +11 -0
- package/src/domain/proxy/json-rpc.test.ts +72 -0
- package/src/domain/proxy/json-rpc.ts +53 -0
- package/src/domain/proxy/policy-engine.test.ts +259 -0
- package/src/domain/proxy/policy-engine.ts +137 -0
- package/src/domain/proxy/proxy-bridge.ts +125 -0
- package/src/domain/proxy/proxy-interceptor.test.ts +184 -0
- package/src/domain/proxy/proxy-interceptor.ts +120 -0
- package/src/domain/proxy/proxy-types.ts +35 -0
- package/src/domain/registry/compute-agent-score.test.ts +279 -0
- package/src/domain/registry/compute-agent-score.ts +162 -0
- package/src/domain/reporter/audit-report.test.ts +87 -0
- package/src/domain/reporter/audit-report.ts +116 -0
- package/src/domain/reporter/badge-generator.test.ts +54 -0
- package/src/domain/reporter/badge-generator.ts +40 -0
- package/src/domain/reporter/compliance-md.ts +45 -0
- package/src/domain/reporter/index.ts +7 -0
- package/src/domain/reporter/pdf-renderer.ts +282 -0
- package/src/domain/reporter/share.test.ts +92 -0
- package/src/domain/reporter/share.ts +80 -0
- package/src/domain/scanner/ast/swc-analyzer.test.ts +49 -0
- package/src/domain/scanner/ast/swc-analyzer.ts +124 -0
- package/src/domain/scanner/attestations.ts +97 -0
- package/src/domain/scanner/checks/ai-disclosure.test.ts +90 -0
- package/src/domain/scanner/checks/ai-disclosure.ts +54 -0
- package/src/domain/scanner/checks/ai-literacy.ts +163 -0
- package/src/domain/scanner/checks/behavioral-constraints.test.ts +167 -0
- package/src/domain/scanner/checks/behavioral-constraints.ts +86 -0
- package/src/domain/scanner/checks/compliance-metadata.ts +63 -0
- package/src/domain/scanner/checks/content-marking.ts +74 -0
- package/src/domain/scanner/checks/dep-deep-scan.test.ts +318 -0
- package/src/domain/scanner/checks/dep-deep-scan.ts +137 -0
- package/src/domain/scanner/checks/documentation.test.ts +88 -0
- package/src/domain/scanner/checks/documentation.ts +79 -0
- package/src/domain/scanner/checks/git-history.test.ts +120 -0
- package/src/domain/scanner/checks/git-history.ts +163 -0
- package/src/domain/scanner/checks/gpai-systemic-risk.test.ts +84 -0
- package/src/domain/scanner/checks/gpai-systemic-risk.ts +98 -0
- package/src/domain/scanner/checks/gpai-transparency.ts +94 -0
- package/src/domain/scanner/checks/index.ts +28 -0
- package/src/domain/scanner/checks/industry/index.ts +40 -0
- package/src/domain/scanner/checks/industry/industry.test.ts +287 -0
- package/src/domain/scanner/checks/interaction-logging.test.ts +113 -0
- package/src/domain/scanner/checks/interaction-logging.ts +142 -0
- package/src/domain/scanner/checks/nhi-scanner.test.ts +158 -0
- package/src/domain/scanner/checks/nhi-scanner.ts +78 -0
- package/src/domain/scanner/checks/passport-completeness.test.ts +127 -0
- package/src/domain/scanner/checks/passport-completeness.ts +82 -0
- package/src/domain/scanner/checks/passport-presence.test.ts +56 -0
- package/src/domain/scanner/checks/passport-presence.ts +78 -0
- package/src/domain/scanner/checks/pattern-check-factory.ts +70 -0
- package/src/domain/scanner/checks/permission-scanner.test.ts +279 -0
- package/src/domain/scanner/checks/permission-scanner.ts +90 -0
- package/src/domain/scanner/checks/presence-check-factory.test.ts +124 -0
- package/src/domain/scanner/checks/presence-check-factory.ts +275 -0
- package/src/domain/scanner/compliance-diff.test.ts +165 -0
- package/src/domain/scanner/compliance-diff.ts +138 -0
- package/src/domain/scanner/confidence.test.ts +235 -0
- package/src/domain/scanner/confidence.ts +156 -0
- package/src/domain/scanner/constants.ts +13 -0
- package/src/domain/scanner/create-scanner.ts +573 -0
- package/src/domain/scanner/cross-layer.test.ts +372 -0
- package/src/domain/scanner/cross-layer.ts +232 -0
- package/src/domain/scanner/data/ai-packages.ts +82 -0
- package/src/domain/scanner/debt-calculator.test.ts +89 -0
- package/src/domain/scanner/debt-calculator.ts +111 -0
- package/src/domain/scanner/drift.test.ts +191 -0
- package/src/domain/scanner/drift.ts +73 -0
- package/src/domain/scanner/evidence-store.test.ts +207 -0
- package/src/domain/scanner/evidence-store.ts +195 -0
- package/src/domain/scanner/evidence.test.ts +104 -0
- package/src/domain/scanner/evidence.ts +71 -0
- package/src/domain/scanner/external/bandit-runner.test.ts +45 -0
- package/src/domain/scanner/external/bandit-runner.ts +90 -0
- package/src/domain/scanner/external/checks.ts +321 -0
- package/src/domain/scanner/external/dedup.test.ts +79 -0
- package/src/domain/scanner/external/dedup.ts +94 -0
- package/src/domain/scanner/external/detect-secrets-runner.test.ts +58 -0
- package/src/domain/scanner/external/detect-secrets-runner.ts +81 -0
- package/src/domain/scanner/external/external-scanner.test.ts +221 -0
- package/src/domain/scanner/external/external-scanner.ts +36 -0
- package/src/domain/scanner/external/finding-mapper.test.ts +95 -0
- package/src/domain/scanner/external/finding-mapper.ts +138 -0
- package/src/domain/scanner/external/index.ts +15 -0
- package/src/domain/scanner/external/mappings.ts +93 -0
- package/src/domain/scanner/external/modelscan-runner.test.ts +35 -0
- package/src/domain/scanner/external/modelscan-runner.ts +101 -0
- package/src/domain/scanner/external/path-utils.ts +8 -0
- package/src/domain/scanner/external/runner-port.ts +45 -0
- package/src/domain/scanner/external/semgrep-runner.test.ts +52 -0
- package/src/domain/scanner/external/semgrep-runner.ts +94 -0
- package/src/domain/scanner/external/types.ts +32 -0
- package/src/domain/scanner/finding-attribution.test.ts +444 -0
- package/src/domain/scanner/finding-attribution.ts +195 -0
- package/src/domain/scanner/finding-explainer.test.ts +157 -0
- package/src/domain/scanner/finding-explainer.ts +73 -0
- package/src/domain/scanner/fix-diff-builder.test.ts +272 -0
- package/src/domain/scanner/fix-diff-builder.ts +477 -0
- package/src/domain/scanner/import-graph.test.ts +162 -0
- package/src/domain/scanner/import-graph.ts +198 -0
- package/src/domain/scanner/languages/adapter.test.ts +105 -0
- package/src/domain/scanner/languages/adapter.ts +239 -0
- package/src/domain/scanner/layers/index.ts +24 -0
- package/src/domain/scanner/layers/layer1-files.ts +54 -0
- package/src/domain/scanner/layers/layer2-docs.test.ts +1207 -0
- package/src/domain/scanner/layers/layer2-docs.ts +297 -0
- package/src/domain/scanner/layers/layer2-parsing.ts +217 -0
- package/src/domain/scanner/layers/layer3-config.test.ts +187 -0
- package/src/domain/scanner/layers/layer3-config.ts +279 -0
- package/src/domain/scanner/layers/layer3-parsers.ts +73 -0
- package/src/domain/scanner/layers/layer4-patterns.test.ts +397 -0
- package/src/domain/scanner/layers/layer4-patterns.ts +216 -0
- package/src/domain/scanner/layers/layer5-docs.test.ts +99 -0
- package/src/domain/scanner/layers/layer5-docs.ts +250 -0
- package/src/domain/scanner/layers/layer5-llm.test.ts +146 -0
- package/src/domain/scanner/layers/layer5-llm.ts +262 -0
- package/src/domain/scanner/layers/layer5-targeted.test.ts +93 -0
- package/src/domain/scanner/layers/layer5-targeted.ts +233 -0
- package/src/domain/scanner/layers/lockfile-parsers.test.ts +320 -0
- package/src/domain/scanner/layers/lockfile-parsers.ts +184 -0
- package/src/domain/scanner/regulation-version.test.ts +54 -0
- package/src/domain/scanner/regulation-version.ts +23 -0
- package/src/domain/scanner/role-filter.test.ts +116 -0
- package/src/domain/scanner/role-filter.ts +51 -0
- package/src/domain/scanner/rules/banned-packages-data.ts +553 -0
- package/src/domain/scanner/rules/banned-packages-sdk.ts +65 -0
- package/src/domain/scanner/rules/banned-packages.test.ts +249 -0
- package/src/domain/scanner/rules/banned-packages.ts +55 -0
- package/src/domain/scanner/rules/comment-filter.test.ts +115 -0
- package/src/domain/scanner/rules/comment-filter.ts +297 -0
- package/src/domain/scanner/rules/index.ts +9 -0
- package/src/domain/scanner/rules/nhi-patterns.test.ts +128 -0
- package/src/domain/scanner/rules/nhi-patterns.ts +60 -0
- package/src/domain/scanner/rules/pattern-rules.ts +1152 -0
- package/src/domain/scanner/sbom.test.ts +136 -0
- package/src/domain/scanner/sbom.ts +103 -0
- package/src/domain/scanner/scan-cache.test.ts +136 -0
- package/src/domain/scanner/scan-cache.ts +115 -0
- package/src/domain/scanner/scanner.test.ts +125 -0
- package/src/domain/scanner/score-calculator.test.ts +363 -0
- package/src/domain/scanner/score-calculator.ts +189 -0
- package/src/domain/scanner/security-score.test.ts +107 -0
- package/src/domain/scanner/security-score.ts +116 -0
- package/src/domain/scanner/source-filter.ts +24 -0
- package/src/domain/scanner/validators.ts +223 -0
- package/src/domain/shared/compliance-constants.ts +48 -0
- package/src/domain/shared/disclosure-patterns.ts +16 -0
- package/src/domain/shared/index.ts +6 -0
- package/src/domain/shared/parse-dependencies.ts +21 -0
- package/src/domain/supply-chain/dependency-analyzer.ts +138 -0
- package/src/domain/supply-chain/index.ts +3 -0
- package/src/domain/supply-chain/supply-chain.test.ts +211 -0
- package/src/domain/supply-chain/types.ts +32 -0
- package/src/domain/whatif/config-fixer.ts +187 -0
- package/src/domain/whatif/index.ts +6 -0
- package/src/domain/whatif/scenario-engine.ts +121 -0
- package/src/domain/whatif/simulate-actions.test.ts +161 -0
- package/src/domain/whatif/simulate-actions.ts +114 -0
- package/src/domain/whatif/whatif.test.ts +135 -0
- package/src/e2e/gaps-e2e.test.ts +259 -0
- package/src/e2e/smoke.test.ts +101 -0
- package/src/hooks/hooks-export.test.ts +81 -0
- package/src/hooks/installer.ts +113 -0
- package/src/http/cors.test.ts +38 -0
- package/src/http/create-router.ts +259 -0
- package/src/http/routes/agent.route.ts +380 -0
- package/src/http/routes/audit.route.ts +66 -0
- package/src/http/routes/badge.route.ts +23 -0
- package/src/http/routes/cert.route.ts +66 -0
- package/src/http/routes/chat.route.ts +228 -0
- package/src/http/routes/cost.route.ts +33 -0
- package/src/http/routes/debt.route.ts +29 -0
- package/src/http/routes/disclaimer.route.ts +64 -0
- package/src/http/routes/eval.route.ts +161 -0
- package/src/http/routes/events.route.test.ts +108 -0
- package/src/http/routes/events.route.ts +71 -0
- package/src/http/routes/external-scan.route.ts +24 -0
- package/src/http/routes/file.route.ts +54 -0
- package/src/http/routes/fix.route.ts +219 -0
- package/src/http/routes/frameworks.route.test.ts +66 -0
- package/src/http/routes/frameworks.route.ts +36 -0
- package/src/http/routes/git.route.ts +27 -0
- package/src/http/routes/guided-onboarding.route.ts +65 -0
- package/src/http/routes/import.route.ts +64 -0
- package/src/http/routes/jurisdiction.route.ts +22 -0
- package/src/http/routes/obligations.route.test.ts +122 -0
- package/src/http/routes/obligations.route.ts +110 -0
- package/src/http/routes/onboarding.route.ts +53 -0
- package/src/http/routes/provider.route.ts +42 -0
- package/src/http/routes/proxy.route.ts +40 -0
- package/src/http/routes/redteam.route.ts +84 -0
- package/src/http/routes/report.route.ts +29 -0
- package/src/http/routes/scan.route.ts +104 -0
- package/src/http/routes/share.route.ts +44 -0
- package/src/http/routes/shell.route.ts +27 -0
- package/src/http/routes/status.route.ts +66 -0
- package/src/http/routes/supply-chain.route.ts +121 -0
- package/src/http/routes/sync.route.ts +328 -0
- package/src/http/routes/tools.route.ts +29 -0
- package/src/http/routes/whatif.route.ts +96 -0
- package/src/http/utils/validation.ts +31 -0
- package/src/index.ts +1 -0
- package/src/infra/bundle-fetcher.ts +77 -0
- package/src/infra/cache-storage.ts +34 -0
- package/src/infra/event-bus.ts +31 -0
- package/src/infra/file-collector.ts +61 -0
- package/src/infra/file-ops-adapter.ts +95 -0
- package/src/infra/file-watcher.test.ts +90 -0
- package/src/infra/file-watcher.ts +106 -0
- package/src/infra/git-adapter.ts +93 -0
- package/src/infra/git-history-adapter.ts +41 -0
- package/src/infra/headless-browser.ts +178 -0
- package/src/infra/llm-adapter.test.ts +83 -0
- package/src/infra/llm-adapter.ts +86 -0
- package/src/infra/logger.ts +27 -0
- package/src/infra/project-config.test.ts +74 -0
- package/src/infra/project-config.ts +35 -0
- package/src/infra/rate-limiter.test.ts +36 -0
- package/src/infra/rate-limiter.ts +34 -0
- package/src/infra/retry.ts +46 -0
- package/src/infra/saas-client.ts +123 -0
- package/src/infra/search-adapter.ts +113 -0
- package/src/infra/shell-adapter.ts +68 -0
- package/src/infra/tool-manager.test.ts +99 -0
- package/src/infra/tool-manager.ts +197 -0
- package/src/llm/agents/agent-modes.test.ts +44 -0
- package/src/llm/agents/modes.ts +68 -0
- package/src/llm/routing/cost-routing.test.ts +37 -0
- package/src/llm/routing/cost-tracker.ts +74 -0
- package/src/llm/routing/model-routing.test.ts +79 -0
- package/src/llm/routing/model-routing.ts +38 -0
- package/src/llm/routing/pricing.ts +19 -0
- package/src/llm/sse-protocol.ts +77 -0
- package/src/llm/tool-definitions.ts +83 -0
- package/src/llm/tool-executors.ts +80 -0
- package/src/llm/tools/types.ts +13 -0
- package/src/mcp/create-mcp-stack.ts +82 -0
- package/src/mcp/handlers.ts +245 -0
- package/src/mcp/index.ts +28 -0
- package/src/mcp/mcp-server.test.ts +80 -0
- package/src/mcp/server.ts +79 -0
- package/src/mcp/tools.ts +48 -0
- package/src/onboarding/auto-detect.ts +164 -0
- package/src/onboarding/onboarding.test.ts +89 -0
- package/src/onboarding/profile.ts +169 -0
- package/src/onboarding/questions.ts +112 -0
- package/src/onboarding/wizard.ts +66 -0
- package/src/output/github-issue.ts +32 -0
- package/src/output/json-output.ts +67 -0
- package/src/ports/browser.port.ts +23 -0
- package/src/ports/events.port.ts +28 -0
- package/src/ports/llm.port.ts +23 -0
- package/src/ports/logger.port.ts +6 -0
- package/src/ports/process.port.ts +6 -0
- package/src/ports/scanner.port.ts +15 -0
- package/src/server.ts +134 -0
- package/src/services/badge-service.ts +67 -0
- package/src/services/chat-service.test.ts +162 -0
- package/src/services/chat-service.ts +152 -0
- package/src/services/cost-service.ts +52 -0
- package/src/services/debt-service.ts +65 -0
- package/src/services/eval-integration.test.ts +132 -0
- package/src/services/eval-service.test.ts +373 -0
- package/src/services/eval-service.ts +463 -0
- package/src/services/external-scan-service.ts +60 -0
- package/src/services/file-service.ts +37 -0
- package/src/services/fix-service.test.ts +470 -0
- package/src/services/fix-service.ts +648 -0
- package/src/services/framework-service.test.ts +159 -0
- package/src/services/framework-service.ts +67 -0
- package/src/services/onboarding-service.ts +165 -0
- package/src/services/passport-audit.ts +244 -0
- package/src/services/passport-documents.ts +258 -0
- package/src/services/passport-service-utils.ts +72 -0
- package/src/services/passport-service.test.ts +251 -0
- package/src/services/passport-service.ts +339 -0
- package/src/services/proxy-service.ts +81 -0
- package/src/services/report-service.ts +72 -0
- package/src/services/scan-service.test.ts +470 -0
- package/src/services/scan-service.ts +335 -0
- package/src/services/share-service.ts +108 -0
- package/src/services/shared/backup.ts +23 -0
- package/src/services/status-service.ts +38 -0
- package/src/services/undo-service.test.ts +190 -0
- package/src/services/undo-service.ts +144 -0
- package/src/test-helpers/factories.ts +116 -0
- package/src/types/common.schemas.ts +147 -0
- package/src/types/common.types.ts +292 -0
- package/src/types/contract.test.ts +217 -0
- package/src/types/errors.ts +52 -0
- package/src/types/framework.types.ts +87 -0
- package/src/types/passport-schemas.ts +241 -0
- package/src/types/passport.types.ts +296 -0
- package/src/version.ts +1 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { generateWorkerNotification } from './worker-notification-generator.js';
|
|
3
|
+
import { createMockPassport } from '../../test-helpers/factories.js';
|
|
4
|
+
|
|
5
|
+
const TEMPLATE = `# Template 4: Worker Notification of High-Risk AI Use
|
|
6
|
+
|
|
7
|
+
**Obligation:** eu-ai-act-OBL-012
|
|
8
|
+
**Article:** Article 26(7)
|
|
9
|
+
**For:** Deployers (employers)
|
|
10
|
+
**Format:** DOCX / PDF / Email
|
|
11
|
+
|
|
12
|
+
## Document Structure:
|
|
13
|
+
|
|
14
|
+
### 1. Header
|
|
15
|
+
- From: [Company Name, HR Department / Management]
|
|
16
|
+
- To: [Workers / Works Council / Union Representative]
|
|
17
|
+
- Date: [Date]
|
|
18
|
+
- Subject: Notification of High-Risk AI System Deployment per EU AI Act Article 26(7)
|
|
19
|
+
|
|
20
|
+
### 2. Notification Body
|
|
21
|
+
|
|
22
|
+
Dear [Workers / Works Council],
|
|
23
|
+
|
|
24
|
+
In accordance with Article 26(7) of the EU Artificial Intelligence Act (Regulation (EU) 2024/1689), we hereby inform you that [Company Name] intends to deploy the following high-risk AI system(s) in the workplace:
|
|
25
|
+
|
|
26
|
+
**AI System Details:**
|
|
27
|
+
- System name: [Name]
|
|
28
|
+
- Provider: [Provider name]
|
|
29
|
+
- Purpose: [What the system does in plain language]
|
|
30
|
+
- Deployment date: [Planned date]
|
|
31
|
+
- Affected roles/departments: [List]
|
|
32
|
+
|
|
33
|
+
**How the system works:**
|
|
34
|
+
[Plain language description: what data it processes, what decisions/recommendations it makes, how it affects workers]
|
|
35
|
+
|
|
36
|
+
**Your rights:**
|
|
37
|
+
- Human oversight: All AI-assisted decisions are reviewed by [named person/role] before implementation
|
|
38
|
+
- You have the right to request an explanation of any AI-influenced decision affecting you (Article 86)
|
|
39
|
+
- You may lodge a complaint with [internal contact] or with the national market surveillance authority
|
|
40
|
+
- Your personal data is processed in accordance with GDPR — see our privacy notice [link/reference]
|
|
41
|
+
|
|
42
|
+
**Contact:**
|
|
43
|
+
For questions or concerns about this AI system, please contact: [Name, Title, Email, Phone]
|
|
44
|
+
|
|
45
|
+
Signed: [Management representative name and title]
|
|
46
|
+
|
|
47
|
+
### 3. Acknowledgment
|
|
48
|
+
- [ ] I acknowledge receipt of this notification
|
|
49
|
+
- Employee name: _________________
|
|
50
|
+
- Date: _________________
|
|
51
|
+
- Signature: _________________
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
describe('generateWorkerNotification', () => {
|
|
55
|
+
it('pre-fills system name from manifest', () => {
|
|
56
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
57
|
+
expect(result.markdown).toContain('System name: Test Agent');
|
|
58
|
+
expect(result.prefilledFields).toContain('System name');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('pre-fills provider from manifest', () => {
|
|
62
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
63
|
+
expect(result.markdown).toContain('Provider: OpenAI');
|
|
64
|
+
expect(result.prefilledFields).toContain('Provider');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('pre-fills purpose/description from manifest', () => {
|
|
68
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
69
|
+
expect(result.markdown).toContain('Purpose: An AI agent for testing compliance');
|
|
70
|
+
expect(result.prefilledFields).toContain('Purpose');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('pre-fills company name from owner.team when not provided', () => {
|
|
74
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
75
|
+
expect(result.markdown).toContain('Acme Corp, HR Department / Management');
|
|
76
|
+
expect(result.markdown).toContain('Acme Corp intends to deploy');
|
|
77
|
+
expect(result.prefilledFields).toContain('Company Name');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('uses explicit companyName over manifest.owner.team', () => {
|
|
81
|
+
const result = generateWorkerNotification({
|
|
82
|
+
manifest: createMockPassport(),
|
|
83
|
+
template: TEMPLATE,
|
|
84
|
+
companyName: 'Custom Inc',
|
|
85
|
+
});
|
|
86
|
+
expect(result.markdown).toContain('Custom Inc, HR Department / Management');
|
|
87
|
+
expect(result.markdown).toContain('Custom Inc intends to deploy');
|
|
88
|
+
expect(result.markdown).not.toContain('Acme Corp');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('pre-fills human oversight from responsible_person', () => {
|
|
92
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
93
|
+
expect(result.markdown).toContain('reviewed by Jane Doe before');
|
|
94
|
+
expect(result.prefilledFields).toContain('Human oversight person');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('fills contact info when provided', () => {
|
|
98
|
+
const result = generateWorkerNotification({
|
|
99
|
+
manifest: createMockPassport(),
|
|
100
|
+
template: TEMPLATE,
|
|
101
|
+
contactName: 'John Smith',
|
|
102
|
+
contactEmail: 'john@acme.com',
|
|
103
|
+
contactPhone: '+1-555-0100',
|
|
104
|
+
});
|
|
105
|
+
expect(result.markdown).toContain('John Smith, john@acme.com, +1-555-0100');
|
|
106
|
+
expect(result.prefilledFields).toContain('Contact details');
|
|
107
|
+
expect(result.prefilledFields).toContain('Internal contact');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('leaves manual fields as placeholders', () => {
|
|
111
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
112
|
+
expect(result.manualFields).toContain('Worker impact description');
|
|
113
|
+
expect(result.manualFields).toContain('Management signature');
|
|
114
|
+
expect(result.manualFields).toContain('Employee acknowledgment');
|
|
115
|
+
expect(result.manualFields).toContain('Privacy notice reference');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('fills deployment date when provided', () => {
|
|
119
|
+
const result = generateWorkerNotification({
|
|
120
|
+
manifest: createMockPassport(),
|
|
121
|
+
template: TEMPLATE,
|
|
122
|
+
deploymentDate: '2026-04-01',
|
|
123
|
+
});
|
|
124
|
+
expect(result.markdown).toContain('Deployment date: 2026-04-01');
|
|
125
|
+
expect(result.prefilledFields).toContain('Deployment date');
|
|
126
|
+
expect(result.manualFields).not.toContain('Deployment date');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('returns correct prefilledFields/manualFields counts', () => {
|
|
130
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
131
|
+
// Auto-filled: Company Name, Date, System name, Provider, Purpose, Human oversight person
|
|
132
|
+
expect(result.prefilledFields.length).toBeGreaterThanOrEqual(6);
|
|
133
|
+
// Manual: Deployment date, Affected roles, System description, Worker impact, Internal contact,
|
|
134
|
+
// Contact details, Management signature, Recipients, Employee acknowledgment, Privacy notice
|
|
135
|
+
expect(result.manualFields.length).toBeGreaterThanOrEqual(8);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('returns frozen result', () => {
|
|
139
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
140
|
+
expect(Object.isFrozen(result)).toBe(true);
|
|
141
|
+
expect(Object.isFrozen(result.prefilledFields)).toBe(true);
|
|
142
|
+
expect(Object.isFrozen(result.manualFields)).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('fills affected roles when provided', () => {
|
|
146
|
+
const result = generateWorkerNotification({
|
|
147
|
+
manifest: createMockPassport(),
|
|
148
|
+
template: TEMPLATE,
|
|
149
|
+
affectedRoles: 'Customer Support, Sales',
|
|
150
|
+
});
|
|
151
|
+
expect(result.markdown).toContain('Affected roles/departments: Customer Support, Sales');
|
|
152
|
+
expect(result.prefilledFields).toContain('Affected roles');
|
|
153
|
+
expect(result.manualFields).not.toContain('Affected roles');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('fills date with current ISO date', () => {
|
|
157
|
+
const result = generateWorkerNotification({ manifest: createMockPassport(), template: TEMPLATE });
|
|
158
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
159
|
+
expect(result.markdown).toContain(`Date: ${today}`);
|
|
160
|
+
expect(result.prefilledFields).toContain('Date');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { AgentPassport } from '../../types/passport.types.js';
|
|
2
|
+
|
|
3
|
+
// --- Types ---
|
|
4
|
+
|
|
5
|
+
export interface WorkerNotificationInput {
|
|
6
|
+
readonly manifest: AgentPassport;
|
|
7
|
+
readonly template: string;
|
|
8
|
+
readonly companyName?: string;
|
|
9
|
+
readonly contactName?: string;
|
|
10
|
+
readonly contactEmail?: string;
|
|
11
|
+
readonly contactPhone?: string;
|
|
12
|
+
readonly deploymentDate?: string;
|
|
13
|
+
readonly affectedRoles?: string;
|
|
14
|
+
readonly impactDescription?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface WorkerNotificationResult {
|
|
18
|
+
readonly markdown: string;
|
|
19
|
+
readonly prefilledFields: readonly string[];
|
|
20
|
+
readonly manualFields: readonly string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// --- Helpers ---
|
|
24
|
+
|
|
25
|
+
const deriveOversightPerson = (manifest: AgentPassport): string | undefined => {
|
|
26
|
+
if (manifest.owner.responsible_person) return manifest.owner.responsible_person;
|
|
27
|
+
if (manifest.autonomy_level === 'L1' || manifest.autonomy_level === 'L2') {
|
|
28
|
+
return 'the designated human supervisor';
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const buildContactLine = (name?: string, email?: string, phone?: string): string | undefined => {
|
|
34
|
+
const parts = [name, email, phone].filter(Boolean);
|
|
35
|
+
return parts.length > 0 ? parts.join(', ') : undefined;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// --- Generator ---
|
|
39
|
+
|
|
40
|
+
export const generateWorkerNotification = (input: WorkerNotificationInput): WorkerNotificationResult => {
|
|
41
|
+
const { manifest, template, companyName, contactName, contactEmail, contactPhone, deploymentDate, affectedRoles, impactDescription } = input;
|
|
42
|
+
const prefilledFields: string[] = [];
|
|
43
|
+
const manualFields: string[] = [];
|
|
44
|
+
|
|
45
|
+
let markdown = template;
|
|
46
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
47
|
+
|
|
48
|
+
// 1. Company Name — use input or fall back to manifest.owner.team
|
|
49
|
+
const company = companyName ?? manifest.owner.team;
|
|
50
|
+
if (company) {
|
|
51
|
+
markdown = markdown.replaceAll('[Company Name, HR Department / Management]', `${company}, HR Department / Management`);
|
|
52
|
+
markdown = markdown.replaceAll('[Company Name]', company);
|
|
53
|
+
prefilledFields.push('Company Name');
|
|
54
|
+
} else {
|
|
55
|
+
manualFields.push('Company Name');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 2. Date header
|
|
59
|
+
markdown = markdown.replaceAll('[Date]', today);
|
|
60
|
+
prefilledFields.push('Date');
|
|
61
|
+
|
|
62
|
+
// 3. System name
|
|
63
|
+
markdown = markdown.replace('System name: [Name]', `System name: ${manifest.display_name}`);
|
|
64
|
+
prefilledFields.push('System name');
|
|
65
|
+
|
|
66
|
+
// 4. Provider
|
|
67
|
+
markdown = markdown.replace('[Provider name]', manifest.model.provider);
|
|
68
|
+
prefilledFields.push('Provider');
|
|
69
|
+
|
|
70
|
+
// 5. Purpose / description
|
|
71
|
+
markdown = markdown.replace('[What the system does in plain language]', manifest.description);
|
|
72
|
+
prefilledFields.push('Purpose');
|
|
73
|
+
|
|
74
|
+
// 6. Deployment date
|
|
75
|
+
if (deploymentDate) {
|
|
76
|
+
markdown = markdown.replace('[Planned date]', deploymentDate);
|
|
77
|
+
prefilledFields.push('Deployment date');
|
|
78
|
+
} else {
|
|
79
|
+
manualFields.push('Deployment date');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 7. Affected roles
|
|
83
|
+
if (affectedRoles) {
|
|
84
|
+
markdown = markdown.replace('Affected roles/departments: [List]', `Affected roles/departments: ${affectedRoles}`);
|
|
85
|
+
prefilledFields.push('Affected roles');
|
|
86
|
+
} else {
|
|
87
|
+
manualFields.push('Affected roles');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 8. How the system works (impact description)
|
|
91
|
+
if (impactDescription) {
|
|
92
|
+
markdown = markdown.replace(
|
|
93
|
+
'[Plain language description: what data it processes, what decisions/recommendations it makes, how it affects workers]',
|
|
94
|
+
impactDescription,
|
|
95
|
+
);
|
|
96
|
+
prefilledFields.push('System description');
|
|
97
|
+
} else {
|
|
98
|
+
manualFields.push('System description (how it works)');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 9. How it affects you — always manual (deployment-specific)
|
|
102
|
+
manualFields.push('Worker impact description');
|
|
103
|
+
|
|
104
|
+
// 10. Human oversight person
|
|
105
|
+
const oversightPerson = deriveOversightPerson(manifest);
|
|
106
|
+
if (oversightPerson) {
|
|
107
|
+
markdown = markdown.replace('[named person/role]', oversightPerson);
|
|
108
|
+
prefilledFields.push('Human oversight person');
|
|
109
|
+
} else {
|
|
110
|
+
manualFields.push('Human oversight person');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 11. Internal contact for complaints
|
|
114
|
+
if (contactName) {
|
|
115
|
+
markdown = markdown.replace('[internal contact]', contactName);
|
|
116
|
+
prefilledFields.push('Internal contact');
|
|
117
|
+
} else {
|
|
118
|
+
manualFields.push('Internal contact');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 12. Contact details block
|
|
122
|
+
const contactLine = buildContactLine(contactName, contactEmail, contactPhone);
|
|
123
|
+
if (contactLine) {
|
|
124
|
+
markdown = markdown.replace('[Name, Title, Email, Phone]', contactLine);
|
|
125
|
+
prefilledFields.push('Contact details');
|
|
126
|
+
} else {
|
|
127
|
+
manualFields.push('Contact details');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 13-16. Always-manual fields
|
|
131
|
+
manualFields.push('Management signature');
|
|
132
|
+
manualFields.push('Recipients');
|
|
133
|
+
manualFields.push('Employee acknowledgment');
|
|
134
|
+
manualFields.push('Privacy notice reference');
|
|
135
|
+
|
|
136
|
+
return Object.freeze({
|
|
137
|
+
markdown,
|
|
138
|
+
prefilledFields: Object.freeze([...prefilledFields]),
|
|
139
|
+
manualFields: Object.freeze([...manualFields]),
|
|
140
|
+
});
|
|
141
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TargetAdapter port — interface for sending probes to external AI endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Adapters translate generic probes into vendor-specific HTTP requests.
|
|
5
|
+
* The eval system never imports concrete adapters directly; everything
|
|
6
|
+
* goes through this contract.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface TargetResponse {
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly status: number;
|
|
12
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
13
|
+
readonly latencyMs: number;
|
|
14
|
+
readonly raw?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ProbeOptions {
|
|
18
|
+
readonly systemPrompt?: string;
|
|
19
|
+
readonly temperature?: number;
|
|
20
|
+
readonly maxTokens?: number;
|
|
21
|
+
readonly timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TargetAdapter {
|
|
25
|
+
/** Send a single-turn probe. */
|
|
26
|
+
readonly send: (probe: string, options?: ProbeOptions) => Promise<TargetResponse>;
|
|
27
|
+
/** Send a multi-turn probe (main + follow-up). */
|
|
28
|
+
readonly sendMultiTurn: (probes: readonly string[], options?: ProbeOptions) => Promise<readonly TargetResponse[]>;
|
|
29
|
+
/** Check if the target is reachable. */
|
|
30
|
+
readonly checkHealth: () => Promise<boolean>;
|
|
31
|
+
/** Human-readable adapter name (e.g. "openai", "ollama"). */
|
|
32
|
+
readonly name: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Error & resilience helpers ──────────────────────────────────
|
|
36
|
+
|
|
37
|
+
/** Error with HTTP status code for retry logic. */
|
|
38
|
+
export class AdapterError extends Error {
|
|
39
|
+
constructor(readonly statusCode: number, message: string) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.name = 'AdapterError';
|
|
42
|
+
}
|
|
43
|
+
get retryable(): boolean {
|
|
44
|
+
return this.statusCode === 429 || this.statusCode >= 500;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Safely parse JSON from a fetch Response.
|
|
50
|
+
* Throws AdapterError with descriptive message for non-JSON or error responses.
|
|
51
|
+
*/
|
|
52
|
+
export const safeJsonParse = async (res: Response): Promise<Record<string, unknown>> => {
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
// Try JSON error body first, fall back to text snippet
|
|
55
|
+
try {
|
|
56
|
+
const body = await res.json() as Record<string, unknown>;
|
|
57
|
+
const msg = body && typeof body === 'object' && 'error' in body
|
|
58
|
+
? JSON.stringify(body.error)
|
|
59
|
+
: JSON.stringify(body);
|
|
60
|
+
throw new AdapterError(res.status, `API error ${res.status}: ${msg}`);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
if (e instanceof AdapterError) throw e;
|
|
63
|
+
// json() failed — response is HTML or other non-JSON
|
|
64
|
+
throw new AdapterError(res.status, `API error ${res.status}: non-JSON response`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 2xx — parse as JSON
|
|
69
|
+
try {
|
|
70
|
+
return await res.json() as Record<string, unknown>;
|
|
71
|
+
} catch {
|
|
72
|
+
throw new AdapterError(res.status, `Non-JSON response body from ${res.status} response`);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Retry a function on retryable AdapterErrors (429, 5xx).
|
|
78
|
+
* Exponential backoff: 1s, 2s (default). Max 2 retries.
|
|
79
|
+
*/
|
|
80
|
+
export const withRetry = async <T>(
|
|
81
|
+
fn: () => Promise<T>,
|
|
82
|
+
maxRetries = 2,
|
|
83
|
+
baseDelayMs = 1000,
|
|
84
|
+
): Promise<T> => {
|
|
85
|
+
for (let attempt = 0; ; attempt++) {
|
|
86
|
+
try {
|
|
87
|
+
return await fn();
|
|
88
|
+
} catch (err) {
|
|
89
|
+
if (attempt >= maxRetries || !(err instanceof AdapterError) || !err.retryable) throw err;
|
|
90
|
+
const delay = baseDelayMs * Math.pow(2, attempt);
|
|
91
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|