bmad-plus 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +14 -14
  3. package/SECURITY.md +62 -0
  4. package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/_http.py +68 -24
  5. package/package.json +1 -1
  6. package/readme-international/README.de.md +14 -14
  7. package/readme-international/README.es.md +14 -14
  8. package/readme-international/README.fr.md +14 -14
  9. package/src/bmad-plus/agents/agent-quality/SKILL.md +1 -1
  10. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review.md +26 -5
  11. package/src/bmad-plus/packs/pack-seo/SKILL.md +3 -1
  12. package/src/bmad-plus/packs/pack-seo/ref/cwv-thresholds.md +2 -2
  13. package/src/bmad-plus/packs/pack-seo/requirements.txt +1 -1
  14. package/src/bmad-plus/packs/pack-seo/scripts/seo_apis.py +72 -30
  15. package/src/bmad-plus/packs/pack-seo/scripts/seo_crawl.py +36 -24
  16. package/src/bmad-plus/packs/pack-seo/scripts/seo_fetch.py +179 -59
  17. package/src/bmad-plus/packs/pack-seo/scripts/seo_report.py +5 -6
  18. package/src/bmad-plus/packs/pack-seo/scripts/seo_screenshot.py +176 -14
  19. package/src/bmad-plus/packs/pack-shield/README.md +12 -0
  20. package/src/bmad-plus/packs/pack-shield/SKILL.md +7 -1
  21. package/src/bmad-plus/packs/pack-shield/review-rules/access-control.md +10 -0
  22. package/src/bmad-plus/packs/pack-shield/review-rules/ai-integrations.md +10 -0
  23. package/src/bmad-plus/packs/pack-shield/review-rules/change-and-supply-chain.md +10 -0
  24. package/src/bmad-plus/packs/pack-shield/review-rules/cryptography.md +10 -0
  25. package/src/bmad-plus/packs/pack-shield/review-rules/index.yaml +134 -0
  26. package/src/bmad-plus/packs/pack-shield/review-rules/logging.md +10 -0
  27. package/src/bmad-plus/packs/pack-shield/review-rules/personal-data.md +10 -0
  28. package/src/bmad-plus/packs/pack-shield/shared/ai-processing-register-template.yaml +53 -0
  29. package/src/bmad-plus/packs/pack-shield/shared/ai-processing-register.md +32 -0
  30. package/src/bmad-plus/packs/pack-shield/shared/assurance-case-template.yaml +87 -0
  31. package/src/bmad-plus/packs/pack-shield/shared/assurance-case.md +50 -0
  32. package/src/bmad-plus/packs/pack-shield/shield-orchestrator.md +24 -1
  33. package/src/bmad-plus/skills/bmad-plus-uat/SKILL.md +1 -0
  34. package/src/bmad-plus/skills/bmad-plus-uat/template/page.html +5 -4
  35. package/tools/build/generate-adapters.js +7 -0
  36. package/tools/build/generate.js +14 -0
  37. package/tools/cli/bmad-plus-cli.js +2 -0
  38. package/tools/cli/commands/ai-register.js +63 -0
  39. package/tools/cli/commands/assurance.js +162 -0
  40. package/tools/cli/commands/review.js +141 -7
  41. package/tools/cli/lib/ai-register.js +393 -0
  42. package/tools/cli/lib/assurance.js +822 -0
  43. package/tools/cli/lib/control-refs.js +132 -0
  44. package/tools/cli/lib/installation-health.js +17 -0
  45. package/tools/cli/lib/packs.js +60 -2
  46. package/tools/cli/lib/page-origins.js +582 -0
  47. package/tools/cli/lib/review-rules.js +124 -26
  48. package/tools/cli/lib/review.js +493 -10
  49. package/tools/cli/lib/uat.js +22 -5
  50. package/tools/cli/review-rules/index.yaml +9 -0
@@ -5,6 +5,7 @@ const fs = require('node:fs');
5
5
  const path = require('node:path');
6
6
  const crypto = require('node:crypto');
7
7
  const { redactFields } = require('./redact');
8
+ const { foreignAddresses } = require('./page-origins');
8
9
 
9
10
  const SPEC_SCHEMA = 'bmad-plus/uat-spec/2';
10
11
  const RESULTS_SCHEMA = 'bmad-plus/uat-results/2';
@@ -176,6 +177,9 @@ function checkMarkup(value, where, errors) {
176
177
  rest = rest.replace(match[0], '');
177
178
  }
178
179
  if (rest.includes('<')) errors.push(`${where}: a "<" is left outside any allowed tag`);
180
+ // The page renders this text as markup: it is read as the template is, so the page loads
181
+ // nothing from another origin whatever the allowed tags come to be.
182
+ for (const found of foreignAddresses(value)) errors.push(`${where}: ${found}`);
179
183
  }
180
184
 
181
185
  function eachMarkup(spec, visit) {
@@ -575,22 +579,34 @@ const PAGE_GUARANTEES = [
575
579
  what: 'the exported JSON is the run as answered, and nothing is exported before a run exists',
576
580
  markers: ['download(runId + ".json", JSON.stringify(run, null, 2))'],
577
581
  },
582
+ {
583
+ id: 'no-third-party-requests',
584
+ what: 'opening and using the page asks nothing of any origin but its own: no remote font, stylesheet, script, image or frame',
585
+ markers: [],
586
+ // An absence has no marker: the template is read as a browser reads it, and every address
587
+ // it would reach on another origin, in markup, style or script, is refused by name.
588
+ refuses: foreignAddresses,
589
+ },
578
590
  ];
579
591
 
580
592
  /**
581
593
  * Which guarantees a template carries: every marker present, in the required order where one
582
- * is set. Checked on the TEMPLATE, never on the built page: a recipe's own text must not be
583
- * able to satisfy or defeat a marker.
594
+ * is set, and nothing it refuses. Checked on the TEMPLATE, never on the built page: a recipe's
595
+ * own text must not be able to satisfy or defeat a marker.
584
596
  */
585
597
  function pageGuarantees(template) {
586
598
  const missing = [];
587
599
  for (const guarantee of PAGE_GUARANTEES) {
588
- const lost = guarantee.markers.filter((marker) => !template.includes(marker));
600
+ const lost = guarantee.markers
601
+ .filter((marker) => !template.includes(marker))
602
+ .map((marker) => `missing ${marker}`);
589
603
  if (!lost.length && guarantee.order) {
590
604
  const positions = guarantee.order.map((marker) => template.indexOf(marker));
591
605
  if (positions.some((at) => at < 0) || positions.some((at, i) => i && at < positions[i - 1]))
592
- lost.push(`order ${guarantee.order.join(' → ')}`);
606
+ lost.push(`missing order ${guarantee.order.join(' → ')}`);
593
607
  }
608
+ if (guarantee.refuses)
609
+ for (const found of guarantee.refuses(template)) lost.push(`carries ${found}`);
594
610
  if (lost.length) missing.push({ id: guarantee.id, what: guarantee.what, lost });
595
611
  }
596
612
  const carried = PAGE_GUARANTEES.map((g) => g.id).filter(
@@ -607,7 +623,7 @@ function buildPage(spec, options = {}) {
607
623
  if (!guarantees.ok) {
608
624
  throw new Error(
609
625
  `the page template (${options.template ? 'the template given' : TEMPLATE}) lost a guarantee — not built: ${guarantees.missing
610
- .map((entry) => `${entry.id}: ${entry.what} — missing ${entry.lost.join(', ')}`)
626
+ .map((entry) => `${entry.id}: ${entry.what} — ${entry.lost.join(', ')}`)
611
627
  .join('; ')}`
612
628
  );
613
629
  }
@@ -1013,6 +1029,7 @@ module.exports = {
1013
1029
  TRIAGE_SCHEMA,
1014
1030
  DEFAULT_DIR,
1015
1031
  DEFAULT_BUDGET,
1032
+ ALLOWED_TAGS,
1016
1033
  STATES,
1017
1034
  TRIAGE_CLASSES,
1018
1035
  TRIAGE_DECISIONS,
@@ -1,36 +1,45 @@
1
1
  # Built-in review checklists, applied by path. Every matching rule applies to a file.
2
2
  # A project adds, replaces (same id) or disables rules in _bmad/review-rules.yaml.
3
+ # A group is a rule family: parallel reviewers can split one unit by group.
3
4
  schema: bmad-plus/review-rules/1
4
5
  rules:
5
6
  - id: general
6
7
  title: Every change
8
+ group: code
7
9
  globs: ['**']
8
10
  doc: general.md
9
11
  - id: javascript-typescript
10
12
  title: JavaScript and TypeScript
13
+ group: code
11
14
  globs: ['**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}', '**/*.{vue,svelte}']
12
15
  doc: javascript-typescript.md
13
16
  - id: python
14
17
  title: Python
18
+ group: code
15
19
  globs: ['**/*.{py,pyi}']
16
20
  doc: python.md
17
21
  - id: sql-and-migrations
18
22
  title: SQL, queries and migrations
23
+ group: data
19
24
  globs: ['**/*.sql', '**/{migrations,migrate,db/migrate}/**', '**/*.prisma', '**/schema.rb']
20
25
  doc: sql-and-migrations.md
21
26
  - id: shell
22
27
  title: Shell and PowerShell scripts
28
+ group: code
23
29
  globs: ['**/*.{sh,bash,zsh,ps1,psm1}', '**/{Makefile,makefile}']
24
30
  doc: shell.md
25
31
  - id: ci-workflows
26
32
  title: CI workflows
33
+ group: delivery
27
34
  globs: ['.github/workflows/**/*.{yml,yaml}', '**/.gitlab-ci.yml', '**/{bitbucket-pipelines.yml,azure-pipelines.yml}']
28
35
  doc: ci-workflows.md
29
36
  - id: containers
30
37
  title: Containers and deployment manifests
38
+ group: delivery
31
39
  globs: ['**/{Dockerfile,Containerfile}', '**/*.dockerfile', '**/{docker-,}compose*.{yml,yaml}', '**/{k8s,kubernetes,helm,charts}/**/*.{yml,yaml}']
32
40
  doc: containers.md
33
41
  - id: configuration
34
42
  title: Configuration and dependency manifests
43
+ group: delivery
35
44
  globs: ['**/*.{json,yml,yaml,toml,ini,properties}', '**/.env.example', '**/{package.json,pyproject.toml,requirements*.txt,go.mod,Cargo.toml,composer.json}']
36
45
  doc: configuration.md