@ztothez/design-engineering 2.0.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/LICENSE +15 -0
- package/README.md +448 -0
- package/ROADMAP.md +127 -0
- package/SKILL.md +698 -0
- package/V2-ROADMAP.md +431 -0
- package/V3-ROADMAP.md +605 -0
- package/V4-ROADMAP.md +283 -0
- package/clean-room-ux-design-spec.md +1431 -0
- package/dist/cli/aggregate-gates.d.ts +2 -0
- package/dist/cli/aggregate-gates.js +86 -0
- package/dist/cli/aggregate-gates.js.map +1 -0
- package/dist/cli/assess-maintainer-review.d.ts +2 -0
- package/dist/cli/assess-maintainer-review.js +72 -0
- package/dist/cli/assess-maintainer-review.js.map +1 -0
- package/dist/cli/audit.d.ts +2 -0
- package/dist/cli/audit.js +71 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/compile-comparison-review.d.ts +2 -0
- package/dist/cli/compile-comparison-review.js +154 -0
- package/dist/cli/compile-comparison-review.js.map +1 -0
- package/dist/cli/compile-plan.d.ts +2 -0
- package/dist/cli/compile-plan.js +66 -0
- package/dist/cli/compile-plan.js.map +1 -0
- package/dist/cli/evaluate-corpus.d.ts +2 -0
- package/dist/cli/evaluate-corpus.js +65 -0
- package/dist/cli/evaluate-corpus.js.map +1 -0
- package/dist/cli/generate-react.d.ts +2 -0
- package/dist/cli/generate-react.js +83 -0
- package/dist/cli/generate-react.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +58 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/portfolio.d.ts +2 -0
- package/dist/cli/portfolio.js +316 -0
- package/dist/cli/portfolio.js.map +1 -0
- package/dist/cli/quality-gate.d.ts +2 -0
- package/dist/cli/quality-gate.js +131 -0
- package/dist/cli/quality-gate.js.map +1 -0
- package/dist/cli/repair-react.d.ts +2 -0
- package/dist/cli/repair-react.js +163 -0
- package/dist/cli/repair-react.js.map +1 -0
- package/dist/cli/review-heuristics.d.ts +2 -0
- package/dist/cli/review-heuristics.js +68 -0
- package/dist/cli/review-heuristics.js.map +1 -0
- package/dist/cli/validate-brief.d.ts +2 -0
- package/dist/cli/validate-brief.js +58 -0
- package/dist/cli/validate-brief.js.map +1 -0
- package/dist/cli/validate-comparison.d.ts +2 -0
- package/dist/cli/validate-comparison.js +68 -0
- package/dist/cli/validate-comparison.js.map +1 -0
- package/dist/cli/validate-contract.d.ts +2 -0
- package/dist/cli/validate-contract.js +54 -0
- package/dist/cli/validate-contract.js.map +1 -0
- package/dist/cli/validate-design.d.ts +2 -0
- package/dist/cli/validate-design.js +53 -0
- package/dist/cli/validate-design.js.map +1 -0
- package/dist/cli/validate-information.d.ts +2 -0
- package/dist/cli/validate-information.js +53 -0
- package/dist/cli/validate-information.js.map +1 -0
- package/dist/cli/validate-trust.d.ts +2 -0
- package/dist/cli/validate-trust.js +53 -0
- package/dist/cli/validate-trust.js.map +1 -0
- package/dist/cli/verify-ui.d.ts +2 -0
- package/dist/cli/verify-ui.js +181 -0
- package/dist/cli/verify-ui.js.map +1 -0
- package/dist/src/acceptance/evaluator.d.ts +13 -0
- package/dist/src/acceptance/evaluator.js +201 -0
- package/dist/src/acceptance/evaluator.js.map +1 -0
- package/dist/src/acceptance/loader.d.ts +2 -0
- package/dist/src/acceptance/loader.js +18 -0
- package/dist/src/acceptance/loader.js.map +1 -0
- package/dist/src/acceptance/report.d.ts +2 -0
- package/dist/src/acceptance/report.js +18 -0
- package/dist/src/acceptance/report.js.map +1 -0
- package/dist/src/acceptance/schema.d.ts +64 -0
- package/dist/src/acceptance/schema.js +57 -0
- package/dist/src/acceptance/schema.js.map +1 -0
- package/dist/src/acceptance/types.d.ts +47 -0
- package/dist/src/acceptance/types.js +2 -0
- package/dist/src/acceptance/types.js.map +1 -0
- package/dist/src/aggregate/report.d.ts +2 -0
- package/dist/src/aggregate/report.js +33 -0
- package/dist/src/aggregate/report.js.map +1 -0
- package/dist/src/aggregate/runner.d.ts +2 -0
- package/dist/src/aggregate/runner.js +165 -0
- package/dist/src/aggregate/runner.js.map +1 -0
- package/dist/src/aggregate/schema.d.ts +182 -0
- package/dist/src/aggregate/schema.js +54 -0
- package/dist/src/aggregate/schema.js.map +1 -0
- package/dist/src/aggregate/types.d.ts +57 -0
- package/dist/src/aggregate/types.js +2 -0
- package/dist/src/aggregate/types.js.map +1 -0
- package/dist/src/audit/policy.d.ts +3 -0
- package/dist/src/audit/policy.js +45 -0
- package/dist/src/audit/policy.js.map +1 -0
- package/dist/src/audit/report.d.ts +2 -0
- package/dist/src/audit/report.js +32 -0
- package/dist/src/audit/report.js.map +1 -0
- package/dist/src/audit/rules/accessibility-name.d.ts +2 -0
- package/dist/src/audit/rules/accessibility-name.js +64 -0
- package/dist/src/audit/rules/accessibility-name.js.map +1 -0
- package/dist/src/audit/rules/component-size.d.ts +2 -0
- package/dist/src/audit/rules/component-size.js +27 -0
- package/dist/src/audit/rules/component-size.js.map +1 -0
- package/dist/src/audit/rules/credential-placeholder.d.ts +2 -0
- package/dist/src/audit/rules/credential-placeholder.js +83 -0
- package/dist/src/audit/rules/credential-placeholder.js.map +1 -0
- package/dist/src/audit/rules/helpers.d.ts +16 -0
- package/dist/src/audit/rules/helpers.js +64 -0
- package/dist/src/audit/rules/helpers.js.map +1 -0
- package/dist/src/audit/rules/index.d.ts +2 -0
- package/dist/src/audit/rules/index.js +23 -0
- package/dist/src/audit/rules/index.js.map +1 -0
- package/dist/src/audit/rules/interactive-integrity.d.ts +2 -0
- package/dist/src/audit/rules/interactive-integrity.js +111 -0
- package/dist/src/audit/rules/interactive-integrity.js.map +1 -0
- package/dist/src/audit/rules/mixed-responsibilities.d.ts +2 -0
- package/dist/src/audit/rules/mixed-responsibilities.js +39 -0
- package/dist/src/audit/rules/mixed-responsibilities.js.map +1 -0
- package/dist/src/audit/rules/mock-production-path.d.ts +2 -0
- package/dist/src/audit/rules/mock-production-path.js +39 -0
- package/dist/src/audit/rules/mock-production-path.js.map +1 -0
- package/dist/src/audit/rules/network-state.d.ts +2 -0
- package/dist/src/audit/rules/network-state.js +39 -0
- package/dist/src/audit/rules/network-state.js.map +1 -0
- package/dist/src/audit/rules/operational-claim.d.ts +2 -0
- package/dist/src/audit/rules/operational-claim.js +94 -0
- package/dist/src/audit/rules/operational-claim.js.map +1 -0
- package/dist/src/audit/rules/placeholder-interaction.d.ts +2 -0
- package/dist/src/audit/rules/placeholder-interaction.js +46 -0
- package/dist/src/audit/rules/placeholder-interaction.js.map +1 -0
- package/dist/src/audit/rules/raw-design-values.d.ts +2 -0
- package/dist/src/audit/rules/raw-design-values.js +97 -0
- package/dist/src/audit/rules/raw-design-values.js.map +1 -0
- package/dist/src/audit/scanner.d.ts +2 -0
- package/dist/src/audit/scanner.js +215 -0
- package/dist/src/audit/scanner.js.map +1 -0
- package/dist/src/audit/types.d.ts +62 -0
- package/dist/src/audit/types.js +2 -0
- package/dist/src/audit/types.js.map +1 -0
- package/dist/src/comparison/evaluator.d.ts +2 -0
- package/dist/src/comparison/evaluator.js +478 -0
- package/dist/src/comparison/evaluator.js.map +1 -0
- package/dist/src/comparison/loader.d.ts +3 -0
- package/dist/src/comparison/loader.js +26 -0
- package/dist/src/comparison/loader.js.map +1 -0
- package/dist/src/comparison/maintainer.d.ts +47 -0
- package/dist/src/comparison/maintainer.js +218 -0
- package/dist/src/comparison/maintainer.js.map +1 -0
- package/dist/src/comparison/report.d.ts +2 -0
- package/dist/src/comparison/report.js +48 -0
- package/dist/src/comparison/report.js.map +1 -0
- package/dist/src/comparison/schema.d.ts +464 -0
- package/dist/src/comparison/schema.js +502 -0
- package/dist/src/comparison/schema.js.map +1 -0
- package/dist/src/contracts/archetypes.d.ts +21 -0
- package/dist/src/contracts/archetypes.js +102 -0
- package/dist/src/contracts/archetypes.js.map +1 -0
- package/dist/src/contracts/journeys.d.ts +7 -0
- package/dist/src/contracts/journeys.js +32 -0
- package/dist/src/contracts/journeys.js.map +1 -0
- package/dist/src/contracts/report.d.ts +2 -0
- package/dist/src/contracts/report.js +33 -0
- package/dist/src/contracts/report.js.map +1 -0
- package/dist/src/contracts/schema.d.ts +1038 -0
- package/dist/src/contracts/schema.js +385 -0
- package/dist/src/contracts/schema.js.map +1 -0
- package/dist/src/contracts/validator.d.ts +12 -0
- package/dist/src/contracts/validator.js +303 -0
- package/dist/src/contracts/validator.js.map +1 -0
- package/dist/src/corpus/evaluator.d.ts +2 -0
- package/dist/src/corpus/evaluator.js +203 -0
- package/dist/src/corpus/evaluator.js.map +1 -0
- package/dist/src/corpus/loader.d.ts +2 -0
- package/dist/src/corpus/loader.js +20 -0
- package/dist/src/corpus/loader.js.map +1 -0
- package/dist/src/corpus/report.d.ts +2 -0
- package/dist/src/corpus/report.js +33 -0
- package/dist/src/corpus/report.js.map +1 -0
- package/dist/src/corpus/schema.d.ts +316 -0
- package/dist/src/corpus/schema.js +269 -0
- package/dist/src/corpus/schema.js.map +1 -0
- package/dist/src/design-intelligence/loader.d.ts +2 -0
- package/dist/src/design-intelligence/loader.js +21 -0
- package/dist/src/design-intelligence/loader.js.map +1 -0
- package/dist/src/design-intelligence/report.d.ts +2 -0
- package/dist/src/design-intelligence/report.js +36 -0
- package/dist/src/design-intelligence/report.js.map +1 -0
- package/dist/src/design-intelligence/schema.d.ts +838 -0
- package/dist/src/design-intelligence/schema.js +854 -0
- package/dist/src/design-intelligence/schema.js.map +1 -0
- package/dist/src/design-intelligence/validator.d.ts +2 -0
- package/dist/src/design-intelligence/validator.js +1371 -0
- package/dist/src/design-intelligence/validator.js.map +1 -0
- package/dist/src/design-plan/compiler.d.ts +8 -0
- package/dist/src/design-plan/compiler.js +288 -0
- package/dist/src/design-plan/compiler.js.map +1 -0
- package/dist/src/design-plan/report.d.ts +2 -0
- package/dist/src/design-plan/report.js +28 -0
- package/dist/src/design-plan/report.js.map +1 -0
- package/dist/src/design-plan/schema.d.ts +202 -0
- package/dist/src/design-plan/schema.js +76 -0
- package/dist/src/design-plan/schema.js.map +1 -0
- package/dist/src/generation/loader.d.ts +2 -0
- package/dist/src/generation/loader.js +21 -0
- package/dist/src/generation/loader.js.map +1 -0
- package/dist/src/generation/policy.d.ts +12 -0
- package/dist/src/generation/policy.js +62 -0
- package/dist/src/generation/policy.js.map +1 -0
- package/dist/src/generation/react-typescript.d.ts +6 -0
- package/dist/src/generation/react-typescript.js +538 -0
- package/dist/src/generation/react-typescript.js.map +1 -0
- package/dist/src/generation/report.d.ts +2 -0
- package/dist/src/generation/report.js +21 -0
- package/dist/src/generation/report.js.map +1 -0
- package/dist/src/generation/schema.d.ts +44 -0
- package/dist/src/generation/schema.js +50 -0
- package/dist/src/generation/schema.js.map +1 -0
- package/dist/src/generation/templates/tokens.d.ts +1 -0
- package/dist/src/generation/templates/tokens.js +59 -0
- package/dist/src/generation/templates/tokens.js.map +1 -0
- package/dist/src/heuristics/evaluator.d.ts +2 -0
- package/dist/src/heuristics/evaluator.js +65 -0
- package/dist/src/heuristics/evaluator.js.map +1 -0
- package/dist/src/heuristics/loader.d.ts +2 -0
- package/dist/src/heuristics/loader.js +21 -0
- package/dist/src/heuristics/loader.js.map +1 -0
- package/dist/src/heuristics/report.d.ts +3 -0
- package/dist/src/heuristics/report.js +31 -0
- package/dist/src/heuristics/report.js.map +1 -0
- package/dist/src/heuristics/schema.d.ts +198 -0
- package/dist/src/heuristics/schema.js +197 -0
- package/dist/src/heuristics/schema.js.map +1 -0
- package/dist/src/information-design/loader.d.ts +2 -0
- package/dist/src/information-design/loader.js +21 -0
- package/dist/src/information-design/loader.js.map +1 -0
- package/dist/src/information-design/report.d.ts +2 -0
- package/dist/src/information-design/report.js +27 -0
- package/dist/src/information-design/report.js.map +1 -0
- package/dist/src/information-design/schema.d.ts +370 -0
- package/dist/src/information-design/schema.js +329 -0
- package/dist/src/information-design/schema.js.map +1 -0
- package/dist/src/information-design/validator.d.ts +2 -0
- package/dist/src/information-design/validator.js +242 -0
- package/dist/src/information-design/validator.js.map +1 -0
- package/dist/src/interface-trust/loader.d.ts +2 -0
- package/dist/src/interface-trust/loader.js +21 -0
- package/dist/src/interface-trust/loader.js.map +1 -0
- package/dist/src/interface-trust/report.d.ts +2 -0
- package/dist/src/interface-trust/report.js +26 -0
- package/dist/src/interface-trust/report.js.map +1 -0
- package/dist/src/interface-trust/schema.d.ts +299 -0
- package/dist/src/interface-trust/schema.js +238 -0
- package/dist/src/interface-trust/schema.js.map +1 -0
- package/dist/src/interface-trust/validator.d.ts +2 -0
- package/dist/src/interface-trust/validator.js +283 -0
- package/dist/src/interface-trust/validator.js.map +1 -0
- package/dist/src/portfolio/adapter-report.d.ts +3 -0
- package/dist/src/portfolio/adapter-report.js +38 -0
- package/dist/src/portfolio/adapter-report.js.map +1 -0
- package/dist/src/portfolio/adapters.d.ts +37 -0
- package/dist/src/portfolio/adapters.js +325 -0
- package/dist/src/portfolio/adapters.js.map +1 -0
- package/dist/src/portfolio/evidence.d.ts +9 -0
- package/dist/src/portfolio/evidence.js +233 -0
- package/dist/src/portfolio/evidence.js.map +1 -0
- package/dist/src/portfolio/files.d.ts +8 -0
- package/dist/src/portfolio/files.js +77 -0
- package/dist/src/portfolio/files.js.map +1 -0
- package/dist/src/portfolio/fixture-server.d.ts +11 -0
- package/dist/src/portfolio/fixture-server.js +131 -0
- package/dist/src/portfolio/fixture-server.js.map +1 -0
- package/dist/src/portfolio/loader.d.ts +2 -0
- package/dist/src/portfolio/loader.js +21 -0
- package/dist/src/portfolio/loader.js.map +1 -0
- package/dist/src/portfolio/mcp.d.ts +186 -0
- package/dist/src/portfolio/mcp.js +117 -0
- package/dist/src/portfolio/mcp.js.map +1 -0
- package/dist/src/portfolio/promotion-schema.d.ts +220 -0
- package/dist/src/portfolio/promotion-schema.js +148 -0
- package/dist/src/portfolio/promotion-schema.js.map +1 -0
- package/dist/src/portfolio/promotion.d.ts +4 -0
- package/dist/src/portfolio/promotion.js +160 -0
- package/dist/src/portfolio/promotion.js.map +1 -0
- package/dist/src/portfolio/qualification-schema.d.ts +268 -0
- package/dist/src/portfolio/qualification-schema.js +112 -0
- package/dist/src/portfolio/qualification-schema.js.map +1 -0
- package/dist/src/portfolio/qualification.d.ts +4 -0
- package/dist/src/portfolio/qualification.js +157 -0
- package/dist/src/portfolio/qualification.js.map +1 -0
- package/dist/src/portfolio/registry.d.ts +34 -0
- package/dist/src/portfolio/registry.js +240 -0
- package/dist/src/portfolio/registry.js.map +1 -0
- package/dist/src/portfolio/report.d.ts +4 -0
- package/dist/src/portfolio/report.js +47 -0
- package/dist/src/portfolio/report.js.map +1 -0
- package/dist/src/portfolio/run-schema.d.ts +135 -0
- package/dist/src/portfolio/run-schema.js +81 -0
- package/dist/src/portfolio/run-schema.js.map +1 -0
- package/dist/src/portfolio/runner.d.ts +118 -0
- package/dist/src/portfolio/runner.js +423 -0
- package/dist/src/portfolio/runner.js.map +1 -0
- package/dist/src/portfolio/schema.d.ts +251 -0
- package/dist/src/portfolio/schema.js +317 -0
- package/dist/src/portfolio/schema.js.map +1 -0
- package/dist/src/portfolio/snapshot.d.ts +89 -0
- package/dist/src/portfolio/snapshot.js +548 -0
- package/dist/src/portfolio/snapshot.js.map +1 -0
- package/dist/src/portfolio/taxonomy-schema.d.ts +215 -0
- package/dist/src/portfolio/taxonomy-schema.js +74 -0
- package/dist/src/portfolio/taxonomy-schema.js.map +1 -0
- package/dist/src/portfolio/taxonomy.d.ts +5 -0
- package/dist/src/portfolio/taxonomy.js +236 -0
- package/dist/src/portfolio/taxonomy.js.map +1 -0
- package/dist/src/portfolio/vault.d.ts +53 -0
- package/dist/src/portfolio/vault.js +176 -0
- package/dist/src/portfolio/vault.js.map +1 -0
- package/dist/src/product-brief/loader.d.ts +2 -0
- package/dist/src/product-brief/loader.js +21 -0
- package/dist/src/product-brief/loader.js.map +1 -0
- package/dist/src/product-brief/report.d.ts +2 -0
- package/dist/src/product-brief/report.js +22 -0
- package/dist/src/product-brief/report.js.map +1 -0
- package/dist/src/product-brief/schema.d.ts +367 -0
- package/dist/src/product-brief/schema.js +272 -0
- package/dist/src/product-brief/schema.js.map +1 -0
- package/dist/src/product-brief/validator.d.ts +2 -0
- package/dist/src/product-brief/validator.js +251 -0
- package/dist/src/product-brief/validator.js.map +1 -0
- package/dist/src/product.d.ts +7 -0
- package/dist/src/product.js +28 -0
- package/dist/src/product.js.map +1 -0
- package/dist/src/quality-gate/report.d.ts +2 -0
- package/dist/src/quality-gate/report.js +46 -0
- package/dist/src/quality-gate/report.js.map +1 -0
- package/dist/src/quality-gate/runner.d.ts +2 -0
- package/dist/src/quality-gate/runner.js +175 -0
- package/dist/src/quality-gate/runner.js.map +1 -0
- package/dist/src/quality-gate/schema.d.ts +75 -0
- package/dist/src/quality-gate/schema.js +37 -0
- package/dist/src/quality-gate/schema.js.map +1 -0
- package/dist/src/quality-gate/types.d.ts +49 -0
- package/dist/src/quality-gate/types.js +2 -0
- package/dist/src/quality-gate/types.js.map +1 -0
- package/dist/src/repair/loader.d.ts +2 -0
- package/dist/src/repair/loader.js +11 -0
- package/dist/src/repair/loader.js.map +1 -0
- package/dist/src/repair/policy.d.ts +16 -0
- package/dist/src/repair/policy.js +65 -0
- package/dist/src/repair/policy.js.map +1 -0
- package/dist/src/repair/report.d.ts +2 -0
- package/dist/src/repair/report.js +32 -0
- package/dist/src/repair/report.js.map +1 -0
- package/dist/src/repair/runner.d.ts +17 -0
- package/dist/src/repair/runner.js +511 -0
- package/dist/src/repair/runner.js.map +1 -0
- package/dist/src/repair/schema.d.ts +264 -0
- package/dist/src/repair/schema.js +202 -0
- package/dist/src/repair/schema.js.map +1 -0
- package/dist/src/retrieval/report.d.ts +2 -0
- package/dist/src/retrieval/report.js +21 -0
- package/dist/src/retrieval/report.js.map +1 -0
- package/dist/src/retrieval/schema.d.ts +123 -0
- package/dist/src/retrieval/schema.js +77 -0
- package/dist/src/retrieval/schema.js.map +1 -0
- package/dist/src/retrieval/search.d.ts +26 -0
- package/dist/src/retrieval/search.js +415 -0
- package/dist/src/retrieval/search.js.map +1 -0
- package/dist/src/runtime/advanced-checks.d.ts +6 -0
- package/dist/src/runtime/advanced-checks.js +487 -0
- package/dist/src/runtime/advanced-checks.js.map +1 -0
- package/dist/src/runtime/composition-checks.d.ts +5 -0
- package/dist/src/runtime/composition-checks.js +307 -0
- package/dist/src/runtime/composition-checks.js.map +1 -0
- package/dist/src/runtime/interface-checks.d.ts +12 -0
- package/dist/src/runtime/interface-checks.js +224 -0
- package/dist/src/runtime/interface-checks.js.map +1 -0
- package/dist/src/runtime/policy.d.ts +13 -0
- package/dist/src/runtime/policy.js +97 -0
- package/dist/src/runtime/policy.js.map +1 -0
- package/dist/src/runtime/report.d.ts +2 -0
- package/dist/src/runtime/report.js +48 -0
- package/dist/src/runtime/report.js.map +1 -0
- package/dist/src/runtime/schema.d.ts +406 -0
- package/dist/src/runtime/schema.js +308 -0
- package/dist/src/runtime/schema.js.map +1 -0
- package/dist/src/runtime/types.d.ts +177 -0
- package/dist/src/runtime/types.js +2 -0
- package/dist/src/runtime/types.js.map +1 -0
- package/dist/src/runtime/verifier.d.ts +2 -0
- package/dist/src/runtime/verifier.js +1201 -0
- package/dist/src/runtime/verifier.js.map +1 -0
- package/dist/src/server.d.ts +2 -0
- package/dist/src/server.js +1352 -0
- package/dist/src/server.js.map +1 -0
- package/docs/installation.md +337 -0
- package/knowledge-base/INDEX.md +285 -0
- package/knowledge-base/benchmarks/aegisops/CALIBRATION.md +52 -0
- package/knowledge-base/benchmarks/aegisops/MANIFEST.md +56 -0
- package/knowledge-base/benchmarks/aegisops/SOURCE-EVIDENCE.md +45 -0
- package/knowledge-base/benchmarks/aegisops/acceptance-criteria.md +42 -0
- package/knowledge-base/benchmarks/aegisops/anti-patterns.md +19 -0
- package/knowledge-base/benchmarks/aegisops/attestations.template.yaml +3 -0
- package/knowledge-base/benchmarks/aegisops/attestations.yaml +115 -0
- package/knowledge-base/benchmarks/aegisops/journeys.json +91 -0
- package/knowledge-base/benchmarks/aegisops/product-contract.yaml +328 -0
- package/knowledge-base/benchmarks/azure-optimizer/SOURCE-EVIDENCE.md +26 -0
- package/knowledge-base/benchmarks/azure-optimizer/V2-IMPLEMENTATION.md +39 -0
- package/knowledge-base/benchmarks/azure-optimizer/acceptance-criteria.md +23 -0
- package/knowledge-base/benchmarks/azure-optimizer/anti-patterns.md +13 -0
- package/knowledge-base/benchmarks/azure-optimizer/journeys.json +88 -0
- package/knowledge-base/benchmarks/azure-optimizer/product-contract.yaml +216 -0
- package/knowledge-base/benchmarks/azure-optimizer/v2-human-review-methodology.yaml +171 -0
- package/knowledge-base/benchmarks/azure-optimizer/v2-journeys.json +139 -0
- package/knowledge-base/benchmarks/corpus/PROVENANCE.md +21 -0
- package/knowledge-base/benchmarks/corpus/README.md +30 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-negative/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-negative/src/FakeDashboard.tsx +10 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-positive/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/anti-slop-positive/src/Progress.tsx +15 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-negative/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-negative/src/OperationsPanel.tsx +40 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-positive/package.json +9 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-positive/src/Dashboard.tsx +17 -0
- package/knowledge-base/benchmarks/corpus/cases/architecture-positive/src/theme.css +15 -0
- package/knowledge-base/benchmarks/corpus/cases/task-incomplete/SOURCE-EVIDENCE.md +3 -0
- package/knowledge-base/benchmarks/corpus/cases/task-incomplete/journeys.json +20 -0
- package/knowledge-base/benchmarks/corpus/cases/task-incomplete/product-contract.yaml +78 -0
- package/knowledge-base/benchmarks/corpus/corpus.schema.yaml +159 -0
- package/knowledge-base/benchmarks/corpus/corpus.yaml +209 -0
- package/knowledge-base/benchmarks/interface-quality/README.md +26 -0
- package/knowledge-base/benchmarks/interface-quality/SOLO-MAINTAINER-TRACK.md +35 -0
- package/knowledge-base/benchmarks/interface-quality/comparison-methodology-v1.1.schema.yaml +288 -0
- package/knowledge-base/benchmarks/interface-quality/comparison-methodology.schema.yaml +235 -0
- package/knowledge-base/benchmarks/interface-quality/comparison-methodology.template.yaml +181 -0
- package/knowledge-base/benchmarks/interface-quality/evidence/example-runtime-report.json +11 -0
- package/knowledge-base/benchmarks/interface-quality/review-session.schema.yaml +14 -0
- package/knowledge-base/benchmarks/interface-quality/review.schema.yaml +296 -0
- package/knowledge-base/benchmarks/interface-quality/review.template.yaml +43 -0
- package/knowledge-base/benchmarks/portfolio-corpus/ADAPTERS.md +68 -0
- package/knowledge-base/benchmarks/portfolio-corpus/PORTFOLIO-RUNNER.md +131 -0
- package/knowledge-base/benchmarks/portfolio-corpus/PRODUCT-TASK-CONTRACTS.md +29 -0
- package/knowledge-base/benchmarks/portfolio-corpus/PROMOTED-RULES.md +31 -0
- package/knowledge-base/benchmarks/portfolio-corpus/archetype-profiles.yaml +26 -0
- package/knowledge-base/benchmarks/portfolio-corpus/product-task-profile.schema.yaml +105 -0
- package/knowledge-base/benchmarks/portfolio-corpus/registry.schema.yaml +188 -0
- package/knowledge-base/benchmarks/portfolio-corpus/registry.template.yaml +63 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/component-size-abstention.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/component-size-negative.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/component-size-positive.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/interactive-integrity-abstention.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/interactive-integrity-negative.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/interactive-integrity-positive.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/raw-design-values-abstention.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/raw-design-values-negative.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-fixtures/raw-design-values-positive.json +10 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-holdout-evaluation.template.json +14 -0
- package/knowledge-base/benchmarks/portfolio-corpus/rule-promotion-evidence.template.json +24 -0
- package/knowledge-base/benchmarks/portfolio-corpus/v3-command-evidence.template.json +17 -0
- package/knowledge-base/benchmarks/portfolio-corpus/v3-qualification-evidence.template.json +29 -0
- package/knowledge-base/benchmarks/scenestart/CALIBRATION.md +95 -0
- package/knowledge-base/benchmarks/scenestart/MANIFEST.md +53 -0
- package/knowledge-base/benchmarks/scenestart/SOURCE-EVIDENCE.md +43 -0
- package/knowledge-base/benchmarks/scenestart/acceptance-criteria.md +59 -0
- package/knowledge-base/benchmarks/scenestart/anti-patterns.md +26 -0
- package/knowledge-base/benchmarks/scenestart/attestations.template.yaml +3 -0
- package/knowledge-base/benchmarks/scenestart/attestations.yaml +21 -0
- package/knowledge-base/benchmarks/scenestart/human-review.md +99 -0
- package/knowledge-base/benchmarks/scenestart/human-review.template.md +105 -0
- package/knowledge-base/benchmarks/scenestart/journeys.json +141 -0
- package/knowledge-base/benchmarks/scenestart/product-contract.yaml +427 -0
- package/knowledge-base/dependencies.yaml +69 -0
- package/knowledge-base/design-intelligence/MASTER.md +87 -0
- package/knowledge-base/design-intelligence/asset-generation.md +66 -0
- package/knowledge-base/design-intelligence/brand-systems.md +69 -0
- package/knowledge-base/design-intelligence/closed-loop-repair.md +95 -0
- package/knowledge-base/design-intelligence/design-deliverable.schema.yaml +1194 -0
- package/knowledge-base/design-intelligence/design-deliverable.template.yaml +591 -0
- package/knowledge-base/design-intelligence/design-plan.md +78 -0
- package/knowledge-base/design-intelligence/design-plan.schema.yaml +621 -0
- package/knowledge-base/design-intelligence/figma-production.md +63 -0
- package/knowledge-base/design-intelligence/generation-adapter.md +72 -0
- package/knowledge-base/design-intelligence/generation-adapter.schema.yaml +47 -0
- package/knowledge-base/design-intelligence/iconography.md +46 -0
- package/knowledge-base/design-intelligence/information-design.md +104 -0
- package/knowledge-base/design-intelligence/information-design.schema.yaml +390 -0
- package/knowledge-base/design-intelligence/information-design.template.yaml +281 -0
- package/knowledge-base/design-intelligence/interaction-recovery-verification.md +72 -0
- package/knowledge-base/design-intelligence/interface-trust.md +103 -0
- package/knowledge-base/design-intelligence/interface-trust.schema.yaml +263 -0
- package/knowledge-base/design-intelligence/interface-trust.template.yaml +173 -0
- package/knowledge-base/design-intelligence/licensing-and-provenance.md +59 -0
- package/knowledge-base/design-intelligence/presentation-design.md +56 -0
- package/knowledge-base/design-intelligence/product-design-brief.md +67 -0
- package/knowledge-base/design-intelligence/product-design-brief.schema.yaml +279 -0
- package/knowledge-base/design-intelligence/product-design-brief.template.yaml +225 -0
- package/knowledge-base/design-intelligence/repair-request.schema.yaml +95 -0
- package/knowledge-base/design-intelligence/repair-request.template.yaml +39 -0
- package/knowledge-base/design-intelligence/visual-accessibility.md +56 -0
- package/knowledge-base/design-intelligence/visual-polish.md +172 -0
- package/knowledge-base/maintained/architecture/MASTER.md +22 -0
- package/knowledge-base/maintained/architecture/component-boundaries.md +30 -0
- package/knowledge-base/maintained/architecture/product-platforms.md +25 -0
- package/knowledge-base/maintained/architecture/quality-attributes-and-evaluation.md +35 -0
- package/knowledge-base/maintained/product-patterns/MASTER.md +10 -0
- package/knowledge-base/maintained/product-patterns/ai-workspaces.md +26 -0
- package/knowledge-base/maintained/product-patterns/operational-dashboards.md +22 -0
- package/knowledge-base/provenance.yaml +196 -0
- package/knowledge-base/retrieval-scope.yaml +43 -0
- package/knowledge-base/usability-evaluation/HEURISTIC_EVALUATION.md +115 -0
- package/knowledge-base/usability-evaluation/heuristic-review.schema.yaml +210 -0
- package/knowledge-base/usability-evaluation/heuristic-review.template.yaml +37 -0
- package/package.json +133 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const DEFAULT_AUDIT_POLICY = {
|
|
2
|
+
componentLineWarning: 400,
|
|
3
|
+
mixedResponsibilitiesMinLines: 200,
|
|
4
|
+
rawColorWarningCount: 3,
|
|
5
|
+
maxFiles: 5_000,
|
|
6
|
+
maxFileBytes: 2 * 1024 * 1024,
|
|
7
|
+
maxTotalBytes: 50 * 1024 * 1024,
|
|
8
|
+
ignoredDirectories: [
|
|
9
|
+
".git",
|
|
10
|
+
".next",
|
|
11
|
+
".nuxt",
|
|
12
|
+
".output",
|
|
13
|
+
".svelte-kit",
|
|
14
|
+
".turbo",
|
|
15
|
+
".vercel",
|
|
16
|
+
"build",
|
|
17
|
+
"coverage",
|
|
18
|
+
"dist",
|
|
19
|
+
"archive",
|
|
20
|
+
"archives",
|
|
21
|
+
"backups",
|
|
22
|
+
"knowledge-base",
|
|
23
|
+
"legacy",
|
|
24
|
+
"node_modules",
|
|
25
|
+
"public",
|
|
26
|
+
"vendor",
|
|
27
|
+
"venv",
|
|
28
|
+
".venv",
|
|
29
|
+
],
|
|
30
|
+
sourceExtensions: [".css", ".js", ".jsx", ".mjs", ".ts", ".tsx"],
|
|
31
|
+
requiredPackageScripts: ["build", "test"],
|
|
32
|
+
requiredPackageScriptGroups: [["lint", "typecheck"]],
|
|
33
|
+
};
|
|
34
|
+
export function createAuditPolicy(overrides = {}) {
|
|
35
|
+
return {
|
|
36
|
+
...DEFAULT_AUDIT_POLICY,
|
|
37
|
+
...overrides,
|
|
38
|
+
ignoredDirectories: overrides.ignoredDirectories ?? DEFAULT_AUDIT_POLICY.ignoredDirectories,
|
|
39
|
+
sourceExtensions: overrides.sourceExtensions ?? DEFAULT_AUDIT_POLICY.sourceExtensions,
|
|
40
|
+
requiredPackageScripts: overrides.requiredPackageScripts ?? DEFAULT_AUDIT_POLICY.requiredPackageScripts,
|
|
41
|
+
requiredPackageScriptGroups: overrides.requiredPackageScriptGroups ??
|
|
42
|
+
DEFAULT_AUDIT_POLICY.requiredPackageScriptGroups,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/audit/policy.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,oBAAoB,EAAE,GAAG;IACzB,6BAA6B,EAAE,GAAG;IAClC,oBAAoB,EAAE,CAAC;IACvB,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IAC7B,aAAa,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IAC/B,kBAAkB,EAAE;QAClB,MAAM;QACN,OAAO;QACP,OAAO;QACP,SAAS;QACT,aAAa;QACb,QAAQ;QACR,SAAS;QACT,OAAO;QACP,UAAU;QACV,MAAM;QACN,SAAS;QACT,UAAU;QACV,SAAS;QACT,gBAAgB;QAChB,QAAQ;QACR,cAAc;QACd,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,OAAO;KACR;IACD,gBAAgB,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;IAChE,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IACzC,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,YAAkC,EAAE;IACpE,OAAO;QACL,GAAG,oBAAoB;QACvB,GAAG,SAAS;QACZ,kBAAkB,EAChB,SAAS,CAAC,kBAAkB,IAAI,oBAAoB,CAAC,kBAAkB;QACzE,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,gBAAgB;QACrF,sBAAsB,EACpB,SAAS,CAAC,sBAAsB,IAAI,oBAAoB,CAAC,sBAAsB;QACjF,2BAA2B,EACzB,SAAS,CAAC,2BAA2B;YACrC,oBAAoB,CAAC,2BAA2B;KACnD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function findingLocation(finding) {
|
|
2
|
+
const location = finding.line
|
|
3
|
+
? `${finding.file}:${finding.line}${finding.column ? `:${finding.column}` : ""}`
|
|
4
|
+
: finding.file;
|
|
5
|
+
return `\`${location}\``;
|
|
6
|
+
}
|
|
7
|
+
export function formatAuditReport(report) {
|
|
8
|
+
const lines = [
|
|
9
|
+
"# ZtotheZ Design Engineering Repository Architecture Audit",
|
|
10
|
+
"",
|
|
11
|
+
`- Target: \`${report.target}\``,
|
|
12
|
+
`- Files scanned: ${report.filesScanned}`,
|
|
13
|
+
`- Bytes scanned: ${report.bytesScanned}`,
|
|
14
|
+
`- Result: ${report.passed ? "PASS" : "FAIL"}`,
|
|
15
|
+
`- Findings: ${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info`,
|
|
16
|
+
];
|
|
17
|
+
if (report.skippedFiles.length > 0) {
|
|
18
|
+
lines.push(`- Skipped files: ${report.skippedFiles.length}`);
|
|
19
|
+
}
|
|
20
|
+
if (report.findings.length === 0) {
|
|
21
|
+
lines.push("", "No architecture findings were detected by the configured static rules.");
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
lines.push("", "## Findings");
|
|
25
|
+
for (const finding of report.findings) {
|
|
26
|
+
lines.push("", `### ${finding.severity.toUpperCase()} ${finding.ruleId} at ${findingLocation(finding)}`, "", finding.message, "", `Confidence: ${finding.confidence}.`, "", ...finding.evidence.map((evidence) => `- Evidence: ${evidence}`), `- Remediation: ${finding.remediation}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
lines.push("", "## Evidence Boundary", "", "### Verifier Limitations", "", ...report.evidenceBoundary.verifierLimitations.map((entry) => `- ${entry}`), "", "### Human Review Required", "", ...report.evidenceBoundary.humanReviewRequired.map((entry) => `- ${entry}`));
|
|
30
|
+
return lines.join("\n");
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/audit/report.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,OAAqB;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI;QAC3B,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QAChF,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACjB,OAAO,KAAK,QAAQ,IAAI,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,MAAM,KAAK,GAAG;QACZ,4DAA4D;QAC5D,EAAE;QACF,eAAe,MAAM,CAAC,MAAM,IAAI;QAChC,oBAAoB,MAAM,CAAC,YAAY,EAAE;QACzC,oBAAoB,MAAM,CAAC,YAAY,EAAE;QACzC,aAAa,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE;QAC9C,eAAe,MAAM,CAAC,OAAO,CAAC,MAAM,YAAY,MAAM,CAAC,OAAO,CAAC,QAAQ,cAAc,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO;KAChH,CAAC;IAEF,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,wEAAwE,CAAC,CAAC;IAC3F,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CACR,EAAE,EACF,OAAO,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,MAAM,OAAO,eAAe,CAAC,OAAO,CAAC,EAAE,EACxF,EAAE,EACF,OAAO,CAAC,OAAO,EACf,EAAE,EACF,eAAe,OAAO,CAAC,UAAU,GAAG,EACpC,EAAE,EACF,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,QAAQ,EAAE,CAAC,EAChE,kBAAkB,OAAO,CAAC,WAAW,EAAE,CACxC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CACR,EAAE,EACF,sBAAsB,EACtB,EAAE,EACF,0BAA0B,EAC1B,EAAE,EACF,GAAG,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,EAC3E,EAAE,EACF,2BAA2B,EAC3B,EAAE,EACF,GAAG,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAC5E,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { isTestOrStory, nodeLocation, walk } from "./helpers.js";
|
|
3
|
+
function hasAttribute(attributes, names) {
|
|
4
|
+
return attributes.properties.some((property) => ts.isJsxAttribute(property) && names.includes(property.name.getText()));
|
|
5
|
+
}
|
|
6
|
+
function nodeProvidesAccessibleText(node) {
|
|
7
|
+
if (ts.isJsxText(node)) {
|
|
8
|
+
return node.text.trim().length > 0;
|
|
9
|
+
}
|
|
10
|
+
if (ts.isJsxExpression(node) && node.expression) {
|
|
11
|
+
return !ts.isJsxElement(node.expression) && !ts.isJsxSelfClosingElement(node.expression);
|
|
12
|
+
}
|
|
13
|
+
if (ts.isJsxElement(node)) {
|
|
14
|
+
return node.children.some(nodeProvidesAccessibleText);
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
function hasAccessibleText(element) {
|
|
19
|
+
return element.children.some((child) => {
|
|
20
|
+
if (ts.isJsxText(child)) {
|
|
21
|
+
return child.text.trim().length > 0;
|
|
22
|
+
}
|
|
23
|
+
if (ts.isJsxExpression(child) && child.expression) {
|
|
24
|
+
return !ts.isJsxElement(child.expression) && !ts.isJsxSelfClosingElement(child.expression);
|
|
25
|
+
}
|
|
26
|
+
return ts.isJsxElement(child) && child.children.some(nodeProvidesAccessibleText);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export const accessibilityNameRule = {
|
|
30
|
+
id: "ZTDE-A11Y-001",
|
|
31
|
+
evaluate(file) {
|
|
32
|
+
if (!file.sourceFile || isTestOrStory(file.relativePath)) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
const findings = [];
|
|
36
|
+
walk(file.sourceFile, (node) => {
|
|
37
|
+
if (!ts.isJsxElement(node) || node.openingElement.tagName.getText() !== "button") {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const attributes = node.openingElement.attributes;
|
|
41
|
+
if (hasAttribute(attributes, ["aria-label", "aria-labelledby", "title"]) ||
|
|
42
|
+
hasAccessibleText(node)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const containsVisualChild = node.children.some((child) => ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child));
|
|
46
|
+
if (!containsVisualChild) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const location = nodeLocation(file, node.openingElement);
|
|
50
|
+
findings.push({
|
|
51
|
+
ruleId: this.id,
|
|
52
|
+
severity: "error",
|
|
53
|
+
confidence: "high",
|
|
54
|
+
file: file.relativePath,
|
|
55
|
+
...location,
|
|
56
|
+
message: "Icon-only button has no detectable accessible name.",
|
|
57
|
+
evidence: ["Button contains a visual child but no text, aria-label, aria-labelledby, or title."],
|
|
58
|
+
remediation: "Add a concise accessible name that describes the button action.",
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
return findings;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=accessibility-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-name.js","sourceRoot":"","sources":["../../../../src/audit/rules/accessibility-name.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { findLargestComponent } from "./helpers.js";
|
|
2
|
+
export const componentSizeRule = {
|
|
3
|
+
id: "ZTDE-ARCH-001",
|
|
4
|
+
evaluate(file, policy) {
|
|
5
|
+
const component = findLargestComponent(file);
|
|
6
|
+
if (!component || component.lines <= policy.componentLineWarning) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
ruleId: this.id,
|
|
12
|
+
severity: "warning",
|
|
13
|
+
confidence: "high",
|
|
14
|
+
file: file.relativePath,
|
|
15
|
+
line: component.line,
|
|
16
|
+
column: component.column,
|
|
17
|
+
message: `${component.name} spans ${component.lines} lines, exceeding the ${policy.componentLineWarning}-line review threshold.`,
|
|
18
|
+
evidence: [
|
|
19
|
+
"The measured function contains JSX.",
|
|
20
|
+
`Component span: ${component.lines} lines.`,
|
|
21
|
+
],
|
|
22
|
+
remediation: "Review responsibility boundaries and extract cohesive domain, orchestration, or presentation units. Do not split solely to satisfy the threshold.",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=component-size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-size.js","sourceRoot":"","sources":["../../../../src/audit/rules/component-size.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,CAAC,MAAM,iBAAiB,GAAc;IAC1C,EAAE,EAAE,eAAe;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM;QACnB,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,KAAK,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACjE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL;gBACE,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,QAAQ,EAAE,SAAS;gBACnB,UAAU,EAAE,MAAM;gBAClB,IAAI,EAAE,IAAI,CAAC,YAAY;gBACvB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,UAAU,SAAS,CAAC,KAAK,yBAAyB,MAAM,CAAC,oBAAoB,yBAAyB;gBAChI,QAAQ,EAAE;oBACR,qCAAqC;oBACrC,mBAAmB,SAAS,CAAC,KAAK,SAAS;iBAC5C;gBACD,WAAW,EACT,mJAAmJ;aACtJ;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { isTestOrStory, nodeLocation, walk } from "./helpers.js";
|
|
3
|
+
const sensitiveNames = new Set([
|
|
4
|
+
"apikey",
|
|
5
|
+
"accesstoken",
|
|
6
|
+
"authtoken",
|
|
7
|
+
"clientsecret",
|
|
8
|
+
"credential",
|
|
9
|
+
"credentials",
|
|
10
|
+
"password",
|
|
11
|
+
"privatekey",
|
|
12
|
+
"secret",
|
|
13
|
+
"token",
|
|
14
|
+
]);
|
|
15
|
+
function normalizedName(node) {
|
|
16
|
+
const value = ts.isIdentifier(node) || ts.isPrivateIdentifier(node)
|
|
17
|
+
? node.text
|
|
18
|
+
: ts.isStringLiteral(node) || ts.isNumericLiteral(node)
|
|
19
|
+
? node.text
|
|
20
|
+
: undefined;
|
|
21
|
+
return value?.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
22
|
+
}
|
|
23
|
+
function literalValue(node) {
|
|
24
|
+
if (!node)
|
|
25
|
+
return undefined;
|
|
26
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
|
|
27
|
+
return node.text;
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
function sensitiveAssignment(node) {
|
|
31
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
|
|
32
|
+
const name = normalizedName(node.name);
|
|
33
|
+
const value = literalValue(node.initializer);
|
|
34
|
+
if (name && sensitiveNames.has(name) && value?.trim())
|
|
35
|
+
return { name, value, location: node.name };
|
|
36
|
+
}
|
|
37
|
+
if (ts.isPropertyAssignment(node)) {
|
|
38
|
+
const name = normalizedName(node.name);
|
|
39
|
+
const value = literalValue(node.initializer);
|
|
40
|
+
if (name && sensitiveNames.has(name) && value?.trim())
|
|
41
|
+
return { name, value, location: node.name };
|
|
42
|
+
}
|
|
43
|
+
if (ts.isBinaryExpression(node) &&
|
|
44
|
+
node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
45
|
+
const target = ts.isPropertyAccessExpression(node.left) ? node.left.name : node.left;
|
|
46
|
+
const name = normalizedName(target);
|
|
47
|
+
const value = literalValue(node.right);
|
|
48
|
+
if (name && sensitiveNames.has(name) && value?.trim())
|
|
49
|
+
return { name, value, location: target };
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
export const credentialPlaceholderRule = {
|
|
54
|
+
id: "ZTDE-SEC-001",
|
|
55
|
+
evaluate(file) {
|
|
56
|
+
if (!file.sourceFile || isTestOrStory(file.relativePath))
|
|
57
|
+
return [];
|
|
58
|
+
const findings = [];
|
|
59
|
+
const seen = new Set();
|
|
60
|
+
walk(file.sourceFile, (node) => {
|
|
61
|
+
const assignment = sensitiveAssignment(node);
|
|
62
|
+
if (!assignment || seen.has(assignment.location.getStart(file.sourceFile)))
|
|
63
|
+
return;
|
|
64
|
+
seen.add(assignment.location.getStart(file.sourceFile));
|
|
65
|
+
const location = nodeLocation(file, assignment.location);
|
|
66
|
+
findings.push({
|
|
67
|
+
ruleId: this.id,
|
|
68
|
+
severity: "error",
|
|
69
|
+
confidence: "high",
|
|
70
|
+
file: file.relativePath,
|
|
71
|
+
...location,
|
|
72
|
+
message: "A credential-like field contains a hard-coded non-empty string literal.",
|
|
73
|
+
evidence: [
|
|
74
|
+
`Sensitive field ${assignment.name} is assigned a ${assignment.value.length}-character literal.`,
|
|
75
|
+
"The value is intentionally redacted from audit output.",
|
|
76
|
+
],
|
|
77
|
+
remediation: "Remove the literal. Load credentials from an approved runtime secret source and represent unavailable credentials as an explicit configuration state.",
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
return findings;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=credential-placeholder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-placeholder.js","sourceRoot":"","sources":["../../../../src/audit/rules/credential-placeholder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import type { AuditSourceFile } from "../types.js";
|
|
3
|
+
export type ComponentSpan = {
|
|
4
|
+
name: string;
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
lines: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function nodeLocation(file: AuditSourceFile, node: ts.Node): {
|
|
10
|
+
line: number;
|
|
11
|
+
column: number;
|
|
12
|
+
};
|
|
13
|
+
export declare function walk(node: ts.Node, visitor: (child: ts.Node) => void): void;
|
|
14
|
+
export declare function findLargestComponent(file: AuditSourceFile): ComponentSpan | undefined;
|
|
15
|
+
export declare function lineNumberForOffset(content: string, offset: number): number;
|
|
16
|
+
export declare function isTestOrStory(relativePath: string): boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
export function nodeLocation(file, node) {
|
|
3
|
+
if (!file.sourceFile) {
|
|
4
|
+
return { line: 1, column: 1 };
|
|
5
|
+
}
|
|
6
|
+
const location = file.sourceFile.getLineAndCharacterOfPosition(node.getStart(file.sourceFile));
|
|
7
|
+
return { line: location.line + 1, column: location.character + 1 };
|
|
8
|
+
}
|
|
9
|
+
export function walk(node, visitor) {
|
|
10
|
+
visitor(node);
|
|
11
|
+
node.forEachChild((child) => walk(child, visitor));
|
|
12
|
+
}
|
|
13
|
+
function containsJsx(node) {
|
|
14
|
+
let found = false;
|
|
15
|
+
walk(node, (child) => {
|
|
16
|
+
if (ts.isJsxElement(child) ||
|
|
17
|
+
ts.isJsxSelfClosingElement(child) ||
|
|
18
|
+
ts.isJsxFragment(child)) {
|
|
19
|
+
found = true;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return found;
|
|
23
|
+
}
|
|
24
|
+
function componentName(node) {
|
|
25
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
26
|
+
return node.name.text;
|
|
27
|
+
}
|
|
28
|
+
if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node)) &&
|
|
29
|
+
ts.isVariableDeclaration(node.parent) &&
|
|
30
|
+
ts.isIdentifier(node.parent.name)) {
|
|
31
|
+
return node.parent.name.text;
|
|
32
|
+
}
|
|
33
|
+
return "default component";
|
|
34
|
+
}
|
|
35
|
+
export function findLargestComponent(file) {
|
|
36
|
+
if (!file.sourceFile) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const components = [];
|
|
40
|
+
walk(file.sourceFile, (node) => {
|
|
41
|
+
const isFunction = ts.isFunctionDeclaration(node) ||
|
|
42
|
+
ts.isFunctionExpression(node) ||
|
|
43
|
+
ts.isArrowFunction(node);
|
|
44
|
+
if (!isFunction || !containsJsx(node)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const start = file.sourceFile.getLineAndCharacterOfPosition(node.getStart(file.sourceFile));
|
|
48
|
+
const end = file.sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
49
|
+
components.push({
|
|
50
|
+
name: componentName(node),
|
|
51
|
+
line: start.line + 1,
|
|
52
|
+
column: start.character + 1,
|
|
53
|
+
lines: end.line - start.line + 1,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
return components.sort((left, right) => right.lines - left.lines)[0];
|
|
57
|
+
}
|
|
58
|
+
export function lineNumberForOffset(content, offset) {
|
|
59
|
+
return content.slice(0, offset).split("\n").length;
|
|
60
|
+
}
|
|
61
|
+
export function isTestOrStory(relativePath) {
|
|
62
|
+
return /(?:^|\/)(?:__tests__|fixtures?|stories)(?:\/|$)|\.(?:spec|test|stories)\.[^.]+$/i.test(relativePath);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../src/audit/rules/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { accessibilityNameRule } from "./accessibility-name.js";
|
|
2
|
+
import { componentSizeRule } from "./component-size.js";
|
|
3
|
+
import { credentialPlaceholderRule } from "./credential-placeholder.js";
|
|
4
|
+
import { interactiveIntegrityRule } from "./interactive-integrity.js";
|
|
5
|
+
import { mixedResponsibilitiesRule } from "./mixed-responsibilities.js";
|
|
6
|
+
import { mockProductionPathRule } from "./mock-production-path.js";
|
|
7
|
+
import { networkStateRule } from "./network-state.js";
|
|
8
|
+
import { operationalClaimRule } from "./operational-claim.js";
|
|
9
|
+
import { placeholderInteractionRule } from "./placeholder-interaction.js";
|
|
10
|
+
import { rawDesignValuesRule } from "./raw-design-values.js";
|
|
11
|
+
export const sourceRules = [
|
|
12
|
+
componentSizeRule,
|
|
13
|
+
mixedResponsibilitiesRule,
|
|
14
|
+
credentialPlaceholderRule,
|
|
15
|
+
mockProductionPathRule,
|
|
16
|
+
placeholderInteractionRule,
|
|
17
|
+
interactiveIntegrityRule,
|
|
18
|
+
operationalClaimRule,
|
|
19
|
+
rawDesignValuesRule,
|
|
20
|
+
networkStateRule,
|
|
21
|
+
accessibilityNameRule,
|
|
22
|
+
];
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/audit/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C,iBAAiB;IACjB,yBAAyB;IACzB,yBAAyB;IACzB,sBAAsB;IACtB,0BAA0B;IAC1B,wBAAwB;IACxB,oBAAoB;IACpB,mBAAmB;IACnB,gBAAgB;IAChB,qBAAqB;CACtB,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { isTestOrStory, nodeLocation, walk } from "./helpers.js";
|
|
3
|
+
function attribute(attributes, name) {
|
|
4
|
+
return attributes.properties.find((property) => ts.isJsxAttribute(property) && property.name.getText() === name);
|
|
5
|
+
}
|
|
6
|
+
function literalAttribute(attributes, name) {
|
|
7
|
+
const match = attribute(attributes, name);
|
|
8
|
+
return match?.initializer && ts.isStringLiteral(match.initializer)
|
|
9
|
+
? match.initializer.text.toLowerCase()
|
|
10
|
+
: undefined;
|
|
11
|
+
}
|
|
12
|
+
function hasAnyAttribute(attributes, names) {
|
|
13
|
+
return attributes.properties.some((property) => ts.isJsxSpreadAttribute(property) ||
|
|
14
|
+
(ts.isJsxAttribute(property) && names.includes(property.name.getText())));
|
|
15
|
+
}
|
|
16
|
+
function insideForm(node) {
|
|
17
|
+
let current = node.parent;
|
|
18
|
+
while (current) {
|
|
19
|
+
if (ts.isJsxElement(current) && current.openingElement.tagName.getText() === "form")
|
|
20
|
+
return true;
|
|
21
|
+
current = current.parent;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function openingNode(node) {
|
|
26
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node))
|
|
27
|
+
return node;
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
export const interactiveIntegrityRule = {
|
|
31
|
+
id: "ZTDE-SLOP-003",
|
|
32
|
+
evaluate(file) {
|
|
33
|
+
if (!file.sourceFile || isTestOrStory(file.relativePath))
|
|
34
|
+
return [];
|
|
35
|
+
const findings = [];
|
|
36
|
+
walk(file.sourceFile, (node) => {
|
|
37
|
+
const opening = openingNode(node);
|
|
38
|
+
if (!opening)
|
|
39
|
+
return;
|
|
40
|
+
const tag = opening.tagName.getText();
|
|
41
|
+
const attributes = opening.attributes;
|
|
42
|
+
const location = nodeLocation(file, opening);
|
|
43
|
+
if (tag === "button") {
|
|
44
|
+
const type = literalAttribute(attributes, "type");
|
|
45
|
+
const intentionallyUnavailable = hasAnyAttribute(attributes, ["disabled", "aria-disabled"]);
|
|
46
|
+
const hasHandler = hasAnyAttribute(attributes, [
|
|
47
|
+
"onClick",
|
|
48
|
+
"onPointerUp",
|
|
49
|
+
"onMouseUp",
|
|
50
|
+
"formAction",
|
|
51
|
+
]);
|
|
52
|
+
const submitsForm = type === "submit" || type === "reset" || (type === undefined && insideForm(opening));
|
|
53
|
+
if (!intentionallyUnavailable && !hasHandler && !submitsForm) {
|
|
54
|
+
findings.push({
|
|
55
|
+
ruleId: this.id,
|
|
56
|
+
severity: "error",
|
|
57
|
+
confidence: "high",
|
|
58
|
+
file: file.relativePath,
|
|
59
|
+
...location,
|
|
60
|
+
message: "Button has no detectable action, form behavior, or intentional disabled state.",
|
|
61
|
+
evidence: ["No event handler, formAction, submit/reset behavior, disabled state, or spread props were found."],
|
|
62
|
+
remediation: "Implement the action, bind form behavior, or render a non-interactive element until the action exists.",
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const role = literalAttribute(attributes, "role");
|
|
68
|
+
const hasClick = hasAnyAttribute(attributes, ["onClick", "onPointerUp", "onMouseUp"]);
|
|
69
|
+
const hasKeyboard = hasAnyAttribute(attributes, ["onKeyDown", "onKeyUp", "onKeyPress"]);
|
|
70
|
+
const hasTabStop = hasAnyAttribute(attributes, ["tabIndex"]);
|
|
71
|
+
if (role === "button" && (!hasClick || !hasKeyboard || !hasTabStop)) {
|
|
72
|
+
findings.push({
|
|
73
|
+
ruleId: this.id,
|
|
74
|
+
severity: "error",
|
|
75
|
+
confidence: "high",
|
|
76
|
+
file: file.relativePath,
|
|
77
|
+
...location,
|
|
78
|
+
message: "Custom button semantics are incomplete.",
|
|
79
|
+
evidence: [
|
|
80
|
+
`Detected role=button with click=${hasClick}, keyboard=${hasKeyboard}, tab stop=${hasTabStop}.`,
|
|
81
|
+
],
|
|
82
|
+
remediation: "Use a native button. If a custom control is unavoidable, provide click, Enter or Space keyboard behavior, and tabIndex=0.",
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// A custom JSX component may render an accessible link or control internally. Without an
|
|
87
|
+
// explicit role, static inspection cannot safely infer its resulting DOM semantics.
|
|
88
|
+
const isIntrinsicElement = /^[a-z][a-z0-9]*$/.test(tag);
|
|
89
|
+
if (!isIntrinsicElement)
|
|
90
|
+
return;
|
|
91
|
+
const nativeInteractiveTags = new Set(["input", "option", "select", "summary", "textarea"]);
|
|
92
|
+
const isAnchorWithHref = tag === "a" && hasAnyAttribute(attributes, ["href"]);
|
|
93
|
+
if (nativeInteractiveTags.has(tag) || isAnchorWithHref)
|
|
94
|
+
return;
|
|
95
|
+
if (role !== "button" && hasClick && !hasKeyboard) {
|
|
96
|
+
findings.push({
|
|
97
|
+
ruleId: this.id,
|
|
98
|
+
severity: "warning",
|
|
99
|
+
confidence: "medium",
|
|
100
|
+
file: file.relativePath,
|
|
101
|
+
...location,
|
|
102
|
+
message: "A non-control element has pointer behavior without detectable keyboard semantics.",
|
|
103
|
+
evidence: [`${tag} declares a pointer handler without a keyboard handler or button role.`],
|
|
104
|
+
remediation: "Use a native interactive element or add the complete keyboard and semantic contract.",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return findings;
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=interactive-integrity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-integrity.js","sourceRoot":"","sources":["../../../../src/audit/rules/interactive-integrity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { findLargestComponent } from "./helpers.js";
|
|
2
|
+
const effectPatterns = [
|
|
3
|
+
{ label: "network requests", pattern: /\b(?:fetch|axios\.(?:get|post|put|patch|delete))\s*\(/ },
|
|
4
|
+
{ label: "local storage", pattern: /\b(?:localStorage|sessionStorage)\s*\./ },
|
|
5
|
+
{ label: "browser database access", pattern: /\bindexedDB\s*\./ },
|
|
6
|
+
{ label: "download orchestration", pattern: /\bURL\.createObjectURL\s*\(/ },
|
|
7
|
+
];
|
|
8
|
+
export const mixedResponsibilitiesRule = {
|
|
9
|
+
id: "ZTDE-ARCH-002",
|
|
10
|
+
evaluate(file, policy) {
|
|
11
|
+
const component = findLargestComponent(file);
|
|
12
|
+
if (!component || component.lines < policy.mixedResponsibilitiesMinLines) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const effects = effectPatterns
|
|
16
|
+
.filter(({ pattern }) => pattern.test(file.content))
|
|
17
|
+
.map(({ label }) => label);
|
|
18
|
+
if (effects.length === 0) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
ruleId: this.id,
|
|
24
|
+
severity: "warning",
|
|
25
|
+
confidence: "medium",
|
|
26
|
+
file: file.relativePath,
|
|
27
|
+
line: component.line,
|
|
28
|
+
column: component.column,
|
|
29
|
+
message: `${component.name} combines a large rendering surface with direct side-effect orchestration.`,
|
|
30
|
+
evidence: [
|
|
31
|
+
`Component span: ${component.lines} lines.`,
|
|
32
|
+
`Detected: ${effects.join(", ")}.`,
|
|
33
|
+
],
|
|
34
|
+
remediation: "Move network, persistence, and export policy behind focused hooks or services while keeping user-visible state in the owning feature.",
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=mixed-responsibilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mixed-responsibilities.js","sourceRoot":"","sources":["../../../../src/audit/rules/mixed-responsibilities.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,cAAc,GAAG;IACrB,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,uDAAuD,EAAE;IAC/F,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,wCAAwC,EAAE;IAC7E,EAAE,KAAK,EAAE,yBAAyB,EAAE,OAAO,EAAE,kBAAkB,EAAE;IACjE,EAAE,KAAK,EAAE,wBAAwB,EAAE,OAAO,EAAE,6BAA6B,EAAE;CAC5E,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAc;IAClD,EAAE,EAAE,eAAe;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM;QACnB,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,KAAK,GAAG,MAAM,CAAC,6BAA6B,EAAE,CAAC;YACzE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,cAAc;aAC3B,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aACnD,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL;gBACE,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,QAAQ,EAAE,SAAS;gBACnB,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,IAAI,CAAC,YAAY;gBACvB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,4EAA4E;gBACtG,QAAQ,EAAE;oBACR,mBAAmB,SAAS,CAAC,KAAK,SAAS;oBAC3C,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;iBACnC;gBACD,WAAW,EACT,uIAAuI;aAC1I;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|