@seanmars/tospec 0.19.0-beta.8 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -296
- package/README.md +69 -82
- package/assets/dashboard/app.js +11 -0
- package/assets/dashboard/style.css +7 -0
- package/bin/tospec.js +1 -1
- package/dist/cli/index.d.ts +6 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +120 -112
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/config.d.ts +9 -17
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +300 -145
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dashboard.d.ts +57 -99
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +252 -330
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/decision.d.ts +38 -27
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +301 -131
- package/dist/commands/decision.js.map +1 -1
- package/dist/commands/metrics.d.ts +28 -51
- package/dist/commands/metrics.d.ts.map +1 -1
- package/dist/commands/metrics.js +62 -93
- package/dist/commands/metrics.js.map +1 -1
- package/dist/commands/shared-output.d.ts +12 -27
- package/dist/commands/shared-output.d.ts.map +1 -1
- package/dist/commands/shared-output.js +22 -45
- package/dist/commands/shared-output.js.map +1 -1
- package/dist/commands/show.d.ts +4 -7
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +23 -11
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/validate.d.ts +34 -58
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +228 -142
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/workflow/index.d.ts +1 -5
- package/dist/commands/workflow/index.d.ts.map +1 -1
- package/dist/commands/workflow/index.js +1 -5
- package/dist/commands/workflow/index.js.map +1 -1
- package/dist/commands/workflow/instructions.d.ts +14 -24
- package/dist/commands/workflow/instructions.d.ts.map +1 -1
- package/dist/commands/workflow/instructions.js +230 -132
- package/dist/commands/workflow/instructions.js.map +1 -1
- package/dist/commands/workflow/new-change.d.ts +2 -5
- package/dist/commands/workflow/new-change.d.ts.map +1 -1
- package/dist/commands/workflow/new-change.js +75 -34
- package/dist/commands/workflow/new-change.js.map +1 -1
- package/dist/commands/workflow/schemas.d.ts +1 -5
- package/dist/commands/workflow/schemas.d.ts.map +1 -1
- package/dist/commands/workflow/schemas.js +6 -17
- package/dist/commands/workflow/schemas.js.map +1 -1
- package/dist/commands/workflow/shared.d.ts +37 -42
- package/dist/commands/workflow/shared.d.ts.map +1 -1
- package/dist/commands/workflow/shared.js +23 -54
- package/dist/commands/workflow/shared.js.map +1 -1
- package/dist/commands/workflow/status.d.ts +7 -17
- package/dist/commands/workflow/status.d.ts.map +1 -1
- package/dist/commands/workflow/status.js +57 -72
- package/dist/commands/workflow/status.js.map +1 -1
- package/dist/commands/workflow/templates.d.ts +8 -8
- package/dist/commands/workflow/templates.d.ts.map +1 -1
- package/dist/commands/workflow/templates.js +32 -46
- package/dist/commands/workflow/templates.js.map +1 -1
- package/dist/core/archive.d.ts +33 -31
- package/dist/core/archive.d.ts.map +1 -1
- package/dist/core/archive.js +322 -284
- package/dist/core/archive.js.map +1 -1
- package/dist/core/artifact-graph/graph.d.ts +25 -42
- package/dist/core/artifact-graph/graph.d.ts.map +1 -1
- package/dist/core/artifact-graph/graph.js +45 -63
- package/dist/core/artifact-graph/graph.js.map +1 -1
- package/dist/core/artifact-graph/index.d.ts +1 -1
- package/dist/core/artifact-graph/index.d.ts.map +1 -1
- package/dist/core/artifact-graph/index.js +1 -1
- package/dist/core/artifact-graph/index.js.map +1 -1
- package/dist/core/artifact-graph/instruction-loader.d.ts +54 -120
- package/dist/core/artifact-graph/instruction-loader.d.ts.map +1 -1
- package/dist/core/artifact-graph/instruction-loader.js +129 -111
- package/dist/core/artifact-graph/instruction-loader.js.map +1 -1
- package/dist/core/artifact-graph/outputs.d.ts +9 -23
- package/dist/core/artifact-graph/outputs.d.ts.map +1 -1
- package/dist/core/artifact-graph/outputs.js +45 -38
- package/dist/core/artifact-graph/outputs.js.map +1 -1
- package/dist/core/artifact-graph/resolver.d.ts +36 -81
- package/dist/core/artifact-graph/resolver.d.ts.map +1 -1
- package/dist/core/artifact-graph/resolver.js +60 -101
- package/dist/core/artifact-graph/resolver.js.map +1 -1
- package/dist/core/artifact-graph/schema.d.ts +0 -6
- package/dist/core/artifact-graph/schema.d.ts.map +1 -1
- package/dist/core/artifact-graph/schema.js +7 -32
- package/dist/core/artifact-graph/schema.js.map +1 -1
- package/dist/core/artifact-graph/state.d.ts +1 -8
- package/dist/core/artifact-graph/state.d.ts.map +1 -1
- package/dist/core/artifact-graph/state.js +2 -17
- package/dist/core/artifact-graph/state.js.map +1 -1
- package/dist/core/artifact-graph/stub-detection.d.ts +6 -14
- package/dist/core/artifact-graph/stub-detection.d.ts.map +1 -1
- package/dist/core/artifact-graph/stub-detection.js +13 -16
- package/dist/core/artifact-graph/stub-detection.js.map +1 -1
- package/dist/core/artifact-graph/types.d.ts +4 -0
- package/dist/core/artifact-graph/types.d.ts.map +1 -1
- package/dist/core/artifact-graph/types.js +46 -11
- package/dist/core/artifact-graph/types.js.map +1 -1
- package/dist/core/available-tools.d.ts +3 -12
- package/dist/core/available-tools.d.ts.map +1 -1
- package/dist/core/available-tools.js +4 -13
- package/dist/core/available-tools.js.map +1 -1
- package/dist/core/change-metadata/schema.d.ts +1 -1
- package/dist/core/change-metadata/schema.d.ts.map +1 -1
- package/dist/core/change-metadata/schema.js +10 -7
- package/dist/core/change-metadata/schema.js.map +1 -1
- package/dist/core/change-presenter.d.ts +16 -27
- package/dist/core/change-presenter.d.ts.map +1 -1
- package/dist/core/change-presenter.js +53 -53
- package/dist/core/change-presenter.js.map +1 -1
- package/dist/core/change-status-policy.d.ts +4 -8
- package/dist/core/change-status-policy.d.ts.map +1 -1
- package/dist/core/change-status-policy.js +9 -17
- package/dist/core/change-status-policy.js.map +1 -1
- package/dist/core/codex-metrics.d.ts +25 -45
- package/dist/core/codex-metrics.d.ts.map +1 -1
- package/dist/core/codex-metrics.js +44 -88
- package/dist/core/codex-metrics.js.map +1 -1
- package/dist/core/codex-residue.d.ts +14 -15
- package/dist/core/codex-residue.d.ts.map +1 -1
- package/dist/core/codex-residue.js +18 -22
- package/dist/core/codex-residue.js.map +1 -1
- package/dist/core/command-generation/adapters/claude.d.ts +2 -9
- package/dist/core/command-generation/adapters/claude.d.ts.map +1 -1
- package/dist/core/command-generation/adapters/claude.js +2 -12
- package/dist/core/command-generation/adapters/claude.js.map +1 -1
- package/dist/core/command-generation/adapters/index.d.ts +1 -9
- package/dist/core/command-generation/adapters/index.d.ts.map +1 -1
- package/dist/core/command-generation/adapters/index.js +1 -9
- package/dist/core/command-generation/adapters/index.js.map +1 -1
- package/dist/core/command-generation/generator.d.ts +0 -17
- package/dist/core/command-generation/generator.d.ts.map +1 -1
- package/dist/core/command-generation/generator.js +0 -17
- package/dist/core/command-generation/generator.js.map +1 -1
- package/dist/core/command-generation/index.d.ts +2 -5
- package/dist/core/command-generation/index.d.ts.map +1 -1
- package/dist/core/command-generation/index.js +0 -9
- package/dist/core/command-generation/index.js.map +1 -1
- package/dist/core/command-generation/types.d.ts +10 -36
- package/dist/core/command-generation/types.d.ts.map +1 -1
- package/dist/core/command-generation/types.js +0 -6
- package/dist/core/command-generation/types.js.map +1 -1
- package/dist/core/command-generation/yaml.d.ts +3 -18
- package/dist/core/command-generation/yaml.d.ts.map +1 -1
- package/dist/core/command-generation/yaml.js +5 -23
- package/dist/core/command-generation/yaml.js.map +1 -1
- package/dist/core/config-prompts.d.ts +2 -4
- package/dist/core/config-prompts.d.ts.map +1 -1
- package/dist/core/config-prompts.js +2 -7
- package/dist/core/config-prompts.js.map +1 -1
- package/dist/core/config-schema.d.ts +7 -41
- package/dist/core/config-schema.d.ts.map +1 -1
- package/dist/core/config-schema.js +35 -74
- package/dist/core/config-schema.js.map +1 -1
- package/dist/core/config.d.ts +25 -49
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +22 -45
- package/dist/core/config.js.map +1 -1
- package/dist/core/dashboard-activity.d.ts +7 -9
- package/dist/core/dashboard-activity.d.ts.map +1 -1
- package/dist/core/dashboard-activity.js +34 -25
- package/dist/core/dashboard-activity.js.map +1 -1
- package/dist/core/dashboard-data.d.ts +35 -22
- package/dist/core/dashboard-data.d.ts.map +1 -1
- package/dist/core/dashboard-data.js +57 -72
- package/dist/core/dashboard-data.js.map +1 -1
- package/dist/core/global-config.d.ts +24 -53
- package/dist/core/global-config.d.ts.map +1 -1
- package/dist/core/global-config.js +38 -67
- package/dist/core/global-config.js.map +1 -1
- package/dist/core/init.d.ts +12 -28
- package/dist/core/init.d.ts.map +1 -1
- package/dist/core/init.js +93 -169
- package/dist/core/init.js.map +1 -1
- package/dist/core/list.d.ts.map +1 -1
- package/dist/core/list.js +95 -41
- package/dist/core/list.js.map +1 -1
- package/dist/core/local-server.d.ts +41 -83
- package/dist/core/local-server.d.ts.map +1 -1
- package/dist/core/local-server.js +53 -98
- package/dist/core/local-server.js.map +1 -1
- package/dist/core/markdown-render.d.ts +15 -23
- package/dist/core/markdown-render.d.ts.map +1 -1
- package/dist/core/markdown-render.js +25 -34
- package/dist/core/markdown-render.js.map +1 -1
- package/dist/core/migrate.d.ts +19 -16
- package/dist/core/migrate.d.ts.map +1 -1
- package/dist/core/migrate.js +162 -136
- package/dist/core/migrate.js.map +1 -1
- package/dist/core/parsers/change-parser.d.ts +7 -10
- package/dist/core/parsers/change-parser.d.ts.map +1 -1
- package/dist/core/parsers/change-parser.js +48 -56
- package/dist/core/parsers/change-parser.js.map +1 -1
- package/dist/core/parsers/markdown-parser.d.ts +8 -9
- package/dist/core/parsers/markdown-parser.d.ts.map +1 -1
- package/dist/core/parsers/markdown-parser.js +23 -30
- package/dist/core/parsers/markdown-parser.js.map +1 -1
- package/dist/core/parsers/requirement-blocks.d.ts +43 -15
- package/dist/core/parsers/requirement-blocks.d.ts.map +1 -1
- package/dist/core/parsers/requirement-blocks.js +142 -70
- package/dist/core/parsers/requirement-blocks.js.map +1 -1
- package/dist/core/parsers/requirement-text.d.ts +73 -79
- package/dist/core/parsers/requirement-text.d.ts.map +1 -1
- package/dist/core/parsers/requirement-text.js +137 -79
- package/dist/core/parsers/requirement-text.js.map +1 -1
- package/dist/core/parsers/spec-structure.d.ts.map +1 -1
- package/dist/core/parsers/spec-structure.js +10 -6
- package/dist/core/parsers/spec-structure.js.map +1 -1
- package/dist/core/profiles.d.ts +3 -10
- package/dist/core/profiles.d.ts.map +1 -1
- package/dist/core/profiles.js +5 -12
- package/dist/core/profiles.js.map +1 -1
- package/dist/core/project-config.d.ts +43 -44
- package/dist/core/project-config.d.ts.map +1 -1
- package/dist/core/project-config.js +107 -82
- package/dist/core/project-config.js.map +1 -1
- package/dist/core/project-layout.d.ts +9 -17
- package/dist/core/project-layout.d.ts.map +1 -1
- package/dist/core/project-layout.js +16 -26
- package/dist/core/project-layout.js.map +1 -1
- package/dist/core/root-selection.d.ts +8 -14
- package/dist/core/root-selection.d.ts.map +1 -1
- package/dist/core/root-selection.js +3 -6
- package/dist/core/root-selection.js.map +1 -1
- package/dist/core/rules.d.ts.map +1 -1
- package/dist/core/rules.js +2 -3
- package/dist/core/rules.js.map +1 -1
- package/dist/core/schema-names.d.ts +16 -0
- package/dist/core/schema-names.d.ts.map +1 -0
- package/dist/core/schema-names.js +16 -0
- package/dist/core/schema-names.js.map +1 -0
- package/dist/core/schemas/base.schema.d.ts.map +1 -1
- package/dist/core/schemas/base.schema.js +6 -12
- package/dist/core/schemas/base.schema.js.map +1 -1
- package/dist/core/schemas/change.schema.d.ts +8 -0
- package/dist/core/schemas/change.schema.d.ts.map +1 -1
- package/dist/core/schemas/change.schema.js +41 -10
- package/dist/core/schemas/change.schema.js.map +1 -1
- package/dist/core/shared/index.d.ts +2 -7
- package/dist/core/shared/index.d.ts.map +1 -1
- package/dist/core/shared/index.js +2 -7
- package/dist/core/shared/index.js.map +1 -1
- package/dist/core/shared/rules-generation.d.ts +5 -15
- package/dist/core/shared/rules-generation.d.ts.map +1 -1
- package/dist/core/shared/rules-generation.js +33 -37
- package/dist/core/shared/rules-generation.js.map +1 -1
- package/dist/core/shared/skill-generation.d.ts +28 -43
- package/dist/core/shared/skill-generation.d.ts.map +1 -1
- package/dist/core/shared/skill-generation.js +82 -51
- package/dist/core/shared/skill-generation.js.map +1 -1
- package/dist/core/shared/tool-detection.d.ts +35 -76
- package/dist/core/shared/tool-detection.d.ts.map +1 -1
- package/dist/core/shared/tool-detection.js +73 -93
- package/dist/core/shared/tool-detection.js.map +1 -1
- package/dist/core/skill-metrics.d.ts +36 -63
- package/dist/core/skill-metrics.d.ts.map +1 -1
- package/dist/core/skill-metrics.js +34 -73
- package/dist/core/skill-metrics.js.map +1 -1
- package/dist/core/spec-presenter.d.ts.map +1 -1
- package/dist/core/spec-presenter.js +5 -10
- package/dist/core/spec-presenter.js.map +1 -1
- package/dist/core/specs-apply.d.ts +16 -31
- package/dist/core/specs-apply.d.ts.map +1 -1
- package/dist/core/specs-apply.js +146 -195
- package/dist/core/specs-apply.js.map +1 -1
- package/dist/core/templates/fragments/interview.d.ts +2 -6
- package/dist/core/templates/fragments/interview.d.ts.map +1 -1
- package/dist/core/templates/fragments/interview.js +2 -6
- package/dist/core/templates/fragments/interview.js.map +1 -1
- package/dist/core/templates/fragments/next-step.d.ts +4 -8
- package/dist/core/templates/fragments/next-step.d.ts.map +1 -1
- package/dist/core/templates/fragments/next-step.js +4 -8
- package/dist/core/templates/fragments/next-step.js.map +1 -1
- package/dist/core/templates/fragments/validate.d.ts +13 -0
- package/dist/core/templates/fragments/validate.d.ts.map +1 -0
- package/dist/core/templates/fragments/validate.js +13 -0
- package/dist/core/templates/fragments/validate.js.map +1 -0
- package/dist/core/templates/fragments/verify.d.ts +9 -12
- package/dist/core/templates/fragments/verify.d.ts.map +1 -1
- package/dist/core/templates/fragments/verify.js +9 -12
- package/dist/core/templates/fragments/verify.js.map +1 -1
- package/dist/core/templates/index.d.ts +0 -6
- package/dist/core/templates/index.d.ts.map +1 -1
- package/dist/core/templates/index.js +0 -7
- package/dist/core/templates/index.js.map +1 -1
- package/dist/core/templates/skill-templates.d.ts +1 -5
- package/dist/core/templates/skill-templates.d.ts.map +1 -1
- package/dist/core/templates/skill-templates.js +0 -5
- package/dist/core/templates/skill-templates.js.map +1 -1
- package/dist/core/templates/types.d.ts +3 -7
- package/dist/core/templates/types.d.ts.map +1 -1
- package/dist/core/templates/types.js +0 -3
- package/dist/core/templates/types.js.map +1 -1
- package/dist/core/templates/workflows/apply.d.ts +3 -9
- package/dist/core/templates/workflows/apply.d.ts.map +1 -1
- package/dist/core/templates/workflows/apply.js +11 -13
- package/dist/core/templates/workflows/apply.js.map +1 -1
- package/dist/core/templates/workflows/archive.d.ts +0 -6
- package/dist/core/templates/workflows/archive.d.ts.map +1 -1
- package/dist/core/templates/workflows/archive.js +16 -5
- package/dist/core/templates/workflows/archive.js.map +1 -1
- package/dist/core/templates/workflows/decision.js +3 -3
- package/dist/core/templates/workflows/decision.js.map +1 -1
- package/dist/core/templates/workflows/explore.js +1 -1
- package/dist/core/templates/workflows/grill.d.ts.map +1 -1
- package/dist/core/templates/workflows/grill.js +0 -2
- package/dist/core/templates/workflows/grill.js.map +1 -1
- package/dist/core/templates/workflows/issue.d.ts +0 -6
- package/dist/core/templates/workflows/issue.d.ts.map +1 -1
- package/dist/core/templates/workflows/issue.js +3 -2
- package/dist/core/templates/workflows/issue.js.map +1 -1
- package/dist/core/templates/workflows/propose.d.ts +0 -6
- package/dist/core/templates/workflows/propose.d.ts.map +1 -1
- package/dist/core/templates/workflows/propose.js +2 -2
- package/dist/core/templates/workflows/propose.js.map +1 -1
- package/dist/core/templates/workflows/sync.d.ts +2 -8
- package/dist/core/templates/workflows/sync.d.ts.map +1 -1
- package/dist/core/templates/workflows/sync.js +4 -3
- package/dist/core/templates/workflows/sync.js.map +1 -1
- package/dist/core/templates/workflows/update.d.ts +0 -6
- package/dist/core/templates/workflows/update.d.ts.map +1 -1
- package/dist/core/templates/workflows/update.js +9 -2
- package/dist/core/templates/workflows/update.js.map +1 -1
- package/dist/core/update.d.ts +10 -36
- package/dist/core/update.d.ts.map +1 -1
- package/dist/core/update.js +59 -126
- package/dist/core/update.js.map +1 -1
- package/dist/core/user-state-migration.d.ts +13 -15
- package/dist/core/user-state-migration.d.ts.map +1 -1
- package/dist/core/user-state-migration.js +30 -23
- package/dist/core/user-state-migration.js.map +1 -1
- package/dist/core/validation/constants.d.ts +4 -10
- package/dist/core/validation/constants.d.ts.map +1 -1
- package/dist/core/validation/constants.js +25 -25
- package/dist/core/validation/constants.js.map +1 -1
- package/dist/core/validation/prose-length.d.ts +15 -0
- package/dist/core/validation/prose-length.d.ts.map +1 -0
- package/dist/core/validation/prose-length.js +29 -0
- package/dist/core/validation/prose-length.js.map +1 -0
- package/dist/core/validation/purpose-placeholder.d.ts +9 -16
- package/dist/core/validation/purpose-placeholder.d.ts.map +1 -1
- package/dist/core/validation/purpose-placeholder.js +30 -44
- package/dist/core/validation/purpose-placeholder.js.map +1 -1
- package/dist/core/validation/section-validator.d.ts +4 -4
- package/dist/core/validation/section-validator.d.ts.map +1 -1
- package/dist/core/validation/section-validator.js +30 -12
- package/dist/core/validation/section-validator.js.map +1 -1
- package/dist/core/validation/task-numbering.d.ts +6 -3
- package/dist/core/validation/task-numbering.d.ts.map +1 -1
- package/dist/core/validation/task-numbering.js +23 -11
- package/dist/core/validation/task-numbering.js.map +1 -1
- package/dist/core/validation/types.d.ts +18 -0
- package/dist/core/validation/types.d.ts.map +1 -1
- package/dist/core/validation/types.js +12 -1
- package/dist/core/validation/types.js.map +1 -1
- package/dist/core/validation/validator.d.ts +42 -68
- package/dist/core/validation/validator.d.ts.map +1 -1
- package/dist/core/validation/validator.js +474 -285
- package/dist/core/validation/validator.js.map +1 -1
- package/dist/prompts/searchable-multi-select.d.ts +3 -8
- package/dist/prompts/searchable-multi-select.d.ts.map +1 -1
- package/dist/prompts/searchable-multi-select.js +16 -39
- package/dist/prompts/searchable-multi-select.js.map +1 -1
- package/dist/utils/change-metadata.d.ts +11 -50
- package/dist/utils/change-metadata.d.ts.map +1 -1
- package/dist/utils/change-metadata.js +48 -67
- package/dist/utils/change-metadata.js.map +1 -1
- package/dist/utils/change-utils.d.ts +24 -76
- package/dist/utils/change-utils.d.ts.map +1 -1
- package/dist/utils/change-utils.js +95 -142
- package/dist/utils/change-utils.js.map +1 -1
- package/dist/utils/file-lock.d.ts +39 -0
- package/dist/utils/file-lock.d.ts.map +1 -0
- package/dist/utils/file-lock.js +149 -0
- package/dist/utils/file-lock.js.map +1 -0
- package/dist/utils/file-system.d.ts +12 -32
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +41 -45
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +7 -11
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +11 -11
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/interactive.d.ts +4 -9
- package/dist/utils/interactive.d.ts.map +1 -1
- package/dist/utils/interactive.js +2 -4
- package/dist/utils/interactive.js.map +1 -1
- package/dist/utils/item-discovery.d.ts +10 -20
- package/dist/utils/item-discovery.d.ts.map +1 -1
- package/dist/utils/item-discovery.js +31 -55
- package/dist/utils/item-discovery.js.map +1 -1
- package/dist/utils/link.d.ts +9 -18
- package/dist/utils/link.d.ts.map +1 -1
- package/dist/utils/link.js +9 -18
- package/dist/utils/link.js.map +1 -1
- package/dist/utils/requirement-diff.d.ts +13 -23
- package/dist/utils/requirement-diff.d.ts.map +1 -1
- package/dist/utils/requirement-diff.js +13 -23
- package/dist/utils/requirement-diff.js.map +1 -1
- package/dist/utils/spec-files.d.ts +7 -20
- package/dist/utils/spec-files.d.ts.map +1 -1
- package/dist/utils/spec-files.js +26 -51
- package/dist/utils/spec-files.js.map +1 -1
- package/dist/utils/task-progress.d.ts +11 -9
- package/dist/utils/task-progress.d.ts.map +1 -1
- package/dist/utils/task-progress.js +53 -32
- package/dist/utils/task-progress.js.map +1 -1
- package/dist/utils/timestamp.d.ts +5 -8
- package/dist/utils/timestamp.d.ts.map +1 -1
- package/dist/utils/timestamp.js +5 -8
- package/dist/utils/timestamp.js.map +1 -1
- package/package.json +2 -3
- package/schemas/issue/schema.yaml +8 -1
- package/schemas/issue/templates/spec.md +20 -3
- package/schemas/sdd/schema.yaml +20 -1
- package/schemas/sdd/templates/spec.md +20 -3
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plumbing shared by every local web command (`dashboard`, `metrics`).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `serveAsset` takes its root directory as an argument — the commands serve
|
|
10
|
-
* different asset trees, and parameterising the directory is what lets one
|
|
11
|
-
* implementation serve both.
|
|
4
|
+
* Shared rather than copied per command because several of these are trust
|
|
5
|
+
* boundaries — `isAllowedHostHeader` (DNS rebinding), `serveAsset` (path
|
|
6
|
+
* escape), `assertBindableHost` (bind policy). A second implementation of any of
|
|
7
|
+
* them is a hole that survives fixing the first.
|
|
12
8
|
*/
|
|
13
9
|
import { promises as fs } from 'node:fs';
|
|
14
10
|
import * as path from 'node:path';
|
|
@@ -21,21 +17,12 @@ const ASSET_CONTENT_TYPES = {
|
|
|
21
17
|
};
|
|
22
18
|
/**
|
|
23
19
|
* Canonical form of a bind address or Host-header name, so the sets below hold
|
|
24
|
-
* addresses rather than spellings
|
|
25
|
-
*
|
|
26
|
-
* `::`, `::0` and `0:0:0:0:0:0:0:0` are one address, and every one of them is
|
|
27
|
-
* something a user can legitimately type after `--host`. Matching spellings
|
|
28
|
-
* means the next one nobody thought to list silently takes the wrong branch —
|
|
29
|
-
* which is how `--allow-remote --host ::0` bound every interface and then 403'd
|
|
30
|
-
* every request that arrived on one.
|
|
20
|
+
* addresses rather than spellings: `::`, `::0` and `0:0:0:0:0:0:0:0` are one
|
|
21
|
+
* address a user may type after `--host`.
|
|
31
22
|
*
|
|
32
|
-
* The WHATWG URL parser is the normalizer because it is
|
|
33
|
-
* canonicalizer
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* Anything that does not parse as a host is returned lowercased and otherwise
|
|
37
|
-
* untouched. Every check in this module treats an unrecognized value as neither
|
|
38
|
-
* loopback nor wildcard, which is the refusing side of each of them.
|
|
23
|
+
* The WHATWG URL parser is the normalizer because it is Node's only built-in
|
|
24
|
+
* IPv6/IPv4 canonicalizer. An unparseable value is returned lowercased, and
|
|
25
|
+
* every check here treats it as neither loopback nor wildcard.
|
|
39
26
|
*/
|
|
40
27
|
export function normalizeHost(host) {
|
|
41
28
|
const bare = host.trim().toLowerCase().replace(/^\[|\]$/g, '');
|
|
@@ -55,64 +42,55 @@ export function normalizeHost(host) {
|
|
|
55
42
|
*/
|
|
56
43
|
export const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);
|
|
57
44
|
/**
|
|
58
|
-
* Bind addresses
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* `::ffff:0:0` is the IPv4-mapped spelling of the same unspecified address; it
|
|
63
|
-
* is listed because it survives normalization as a distinct string, not because
|
|
64
|
-
* it means anything different.
|
|
45
|
+
* Bind addresses meaning "every interface", canonical forms only. No client
|
|
46
|
+
* sends these as a Host header, which is why `isAllowedHostHeader`'s literal
|
|
47
|
+
* match can never satisfy them. `::ffff:0:0` is listed because it survives
|
|
48
|
+
* normalization as a distinct string.
|
|
65
49
|
*/
|
|
66
50
|
export const WILDCARD_HOSTS = new Set(['0.0.0.0', '::', '::ffff:0:0']);
|
|
67
51
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
52
|
+
* A URL a browser can actually open for a server bound to `host`. A wildcard
|
|
53
|
+
* bind has no connectable spelling — `http://0.0.0.0:5620` is not visitable —
|
|
54
|
+
* and `dashboard --list` reconstructs the loopback URL the same way.
|
|
55
|
+
*/
|
|
56
|
+
export function connectableUrl(host, port) {
|
|
57
|
+
// Normalized like every other check here: `::0` is a wildcard bind that
|
|
58
|
+
// `acceptsAnyHostHeader` recognises, so printing `http://[::0]:5620` for it
|
|
59
|
+
// handed the user a URL no browser can open.
|
|
60
|
+
const displayHost = WILDCARD_HOSTS.has(normalizeHost(host)) ? '127.0.0.1' : host;
|
|
61
|
+
// IPv6 literals need brackets in a URL; a bare `::1` parses as host `` with a
|
|
62
|
+
// port of `:1`.
|
|
63
|
+
const bracketed = displayHost.includes(':') ? `[${displayHost}]` : displayHost;
|
|
64
|
+
return `http://${bracketed}:${port}`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The bind guard, shared so a new local server cannot silently bind `0.0.0.0`.
|
|
77
68
|
*
|
|
78
|
-
* `
|
|
79
|
-
*
|
|
80
|
-
* the text used to hard-code "Pass `--allow-remote`", a flag `skill-metrics`
|
|
81
|
-
* does not register, so the one command that could not act on the advice was the
|
|
82
|
-
* one being told to. Making it a parameter means a new local server has to state
|
|
83
|
-
* its own escape hatch rather than silently inherit one it may not have.
|
|
69
|
+
* `remedy` is the caller's: `--allow-remote` is a dashboard flag that
|
|
70
|
+
* `skill-metrics` does not register, so each server states its own escape hatch.
|
|
84
71
|
*/
|
|
85
72
|
export function assertBindableHost(host, serverName, allowRemote, remedy) {
|
|
86
73
|
if (LOOPBACK_HOSTS.has(normalizeHost(host)) || allowRemote)
|
|
87
74
|
return;
|
|
88
75
|
throw new Error(`Refusing to bind non-loopback host '${host}': the ${serverName} would be readable by anyone who can reach this machine. ${remedy}`);
|
|
89
76
|
}
|
|
90
|
-
// -----------------------------------------------------------------------------
|
|
91
|
-
// Responses
|
|
92
|
-
// -----------------------------------------------------------------------------
|
|
93
77
|
export function sendJson(res, status, payload) {
|
|
94
78
|
res.writeHead(status, { 'content-type': 'application/json; charset=utf-8' });
|
|
95
79
|
res.end(JSON.stringify(payload));
|
|
96
80
|
}
|
|
97
81
|
/**
|
|
98
|
-
* Absolute path to a shipped asset tree (`assets/<name>`), resolved
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* The depth is load-bearing: compiled to `dist/core/`, two levels up is the
|
|
102
|
-
* package root, which is also what `dist/commands/` yields. Assets are shipped
|
|
103
|
-
* as package `files` and never compiled, so moving this module to a different
|
|
104
|
-
* depth would silently resolve outside the package. Every caller goes through
|
|
105
|
-
* here so that constraint has exactly one home.
|
|
82
|
+
* Absolute path to a shipped asset tree (`assets/<name>`), resolved from this
|
|
83
|
+
* module's own URL. The depth is load-bearing: compiled to `dist/core/`, two
|
|
84
|
+
* levels up is the package root, so moving this module resolves outside it.
|
|
106
85
|
*/
|
|
107
86
|
export function packageAssetsDir(name) {
|
|
108
87
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
109
88
|
return path.join(here, '..', '..', 'assets', name);
|
|
110
89
|
}
|
|
111
90
|
/**
|
|
112
|
-
* Serves one file from `dir`.
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* request and the rest of the filesystem.
|
|
91
|
+
* Serves one file from `dir`. URL parsing already normalises `..`, but a
|
|
92
|
+
* resolved path outside `dir` is refused regardless: this is the only thing
|
|
93
|
+
* between a crafted request and the rest of the filesystem.
|
|
116
94
|
*/
|
|
117
95
|
export async function serveAsset(res, dir, rawName) {
|
|
118
96
|
const name = decodeURIComponent(rawName);
|
|
@@ -134,15 +112,11 @@ export async function serveAsset(res, dir, rawName) {
|
|
|
134
112
|
res.writeHead(200, { 'content-type': `${type}; charset=utf-8` });
|
|
135
113
|
res.end(content);
|
|
136
114
|
}
|
|
137
|
-
// -----------------------------------------------------------------------------
|
|
138
|
-
// Trust boundary
|
|
139
|
-
// -----------------------------------------------------------------------------
|
|
140
115
|
/**
|
|
141
116
|
* DNS-rebinding guard: only requests whose Host header names loopback (or the
|
|
142
117
|
* explicitly bound non-loopback address) are served. A malicious page can make
|
|
143
118
|
* a victim's browser resolve an attacker domain to 127.0.0.1 and read the
|
|
144
|
-
* server's endpoints; the attacker domain in the Host header
|
|
145
|
-
* away.
|
|
119
|
+
* server's endpoints; the attacker domain in the Host header gives that away.
|
|
146
120
|
*/
|
|
147
121
|
export function isAllowedHostHeader(hostHeader, boundHost, acceptAnyHost = false) {
|
|
148
122
|
if (!hostHeader)
|
|
@@ -152,38 +126,31 @@ export function isAllowedHostHeader(hostHeader, boundHost, acceptAnyHost = false
|
|
|
152
126
|
if (!match)
|
|
153
127
|
return false;
|
|
154
128
|
// Normalized on both sides so the comparison is between addresses, not
|
|
155
|
-
// between the
|
|
129
|
+
// between the client's spelling and the operator's.
|
|
156
130
|
const name = normalizeHost(match[1]);
|
|
157
131
|
if (LOOPBACK_HOSTS.has(name))
|
|
158
132
|
return true;
|
|
159
|
-
//
|
|
160
|
-
//
|
|
133
|
+
// Last, and after parsing: the opt-in widens who may be named, not what counts
|
|
134
|
+
// as a name.
|
|
161
135
|
if (acceptAnyHost)
|
|
162
136
|
return true;
|
|
163
137
|
return name === normalizeHost(boundHost);
|
|
164
138
|
}
|
|
165
139
|
/**
|
|
166
|
-
* The Host-header policy, resolved once at startup rather than
|
|
167
|
-
*
|
|
140
|
+
* The Host-header policy, resolved once at startup rather than per request —
|
|
141
|
+
* see decisions/20260910_150312-allow-remote-wildcard-host-policy.md.
|
|
168
142
|
*
|
|
169
143
|
* A wildcard bind has no Host header that can literally match it, so
|
|
170
|
-
* `--allow-remote --host 0.0.0.0`
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* Kept out of `isAllowedHostHeader` on purpose. That predicate cannot see
|
|
176
|
-
* whether `--allow-remote` was passed, and burying "wildcard means trust
|
|
177
|
-
* everyone" inside it would make the assumption invisible at the call site.
|
|
144
|
+
* `--allow-remote --host 0.0.0.0` would listen on every interface then 403 every
|
|
145
|
+
* request. Only that combination is relaxed; a concrete address names the host
|
|
146
|
+
* worth accepting. Kept out of `isAllowedHostHeader` so "wildcard means trust
|
|
147
|
+
* everyone" stays visible at the call site.
|
|
178
148
|
*/
|
|
179
149
|
export function acceptsAnyHostHeader(boundHost, allowRemote) {
|
|
180
150
|
if (!allowRemote)
|
|
181
151
|
return false;
|
|
182
152
|
return WILDCARD_HOSTS.has(normalizeHost(boundHost));
|
|
183
153
|
}
|
|
184
|
-
// -----------------------------------------------------------------------------
|
|
185
|
-
// Lifecycle
|
|
186
|
-
// -----------------------------------------------------------------------------
|
|
187
154
|
/** Resolves once the server is listening, or rejects with the listen error. */
|
|
188
155
|
export function listenOnce(server, port, host) {
|
|
189
156
|
return new Promise((resolve, reject) => {
|
|
@@ -201,17 +168,12 @@ export function listenOnce(server, port, host) {
|
|
|
201
168
|
});
|
|
202
169
|
}
|
|
203
170
|
/**
|
|
204
|
-
* Binds `basePort`, advancing
|
|
205
|
-
*
|
|
206
|
-
* rule — a predictable port you can keep in your head, that still yields rather
|
|
207
|
-
* than failing when something already holds it.
|
|
171
|
+
* Binds `basePort`, advancing on `EADDRINUSE` until one is free, and returns the
|
|
172
|
+
* port actually bound.
|
|
208
173
|
*
|
|
209
|
-
* `port: 0`
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* The attempt bound is a backstop, not a policy: without it a machine that
|
|
214
|
-
* refuses every bind for some other reason would spin through 65k ports.
|
|
174
|
+
* `port: 0` passes straight through — the OS picks a free port, so there is
|
|
175
|
+
* nothing to retry. `maxAttempts` stops a machine that refuses every bind from
|
|
176
|
+
* spinning through 65k ports.
|
|
215
177
|
*/
|
|
216
178
|
export async function listenFrom(server, basePort, host, maxAttempts = 200) {
|
|
217
179
|
let port = basePort;
|
|
@@ -232,14 +194,7 @@ export async function listenFrom(server, basePort, host, maxAttempts = 200) {
|
|
|
232
194
|
const address = server.address();
|
|
233
195
|
return typeof address === 'object' && address ? address.port : port;
|
|
234
196
|
}
|
|
235
|
-
|
|
236
|
-
// Browser
|
|
237
|
-
// -----------------------------------------------------------------------------
|
|
238
|
-
/**
|
|
239
|
-
* Builds the platform command that opens `url` in the default browser.
|
|
240
|
-
* Pure (no side effects) so the platform branching is testable without
|
|
241
|
-
* launching anything.
|
|
242
|
-
*/
|
|
197
|
+
/** Pure, so the platform branching is testable without launching anything. */
|
|
243
198
|
export function browserOpenCommand(url, platform = process.platform) {
|
|
244
199
|
if (platform === 'win32')
|
|
245
200
|
return `start "" "${url}"`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/core/local-server.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/core/local-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,mBAAmB,GAA2B;IAClD,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,UAAU;CACnB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC;QACH,0EAA0E;QAC1E,4DAA4D;QAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1D,OAAO,IAAI,GAAG,CAAC,UAAU,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;AAEzE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;AAEvE;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY;IACvD,wEAAwE;IACxE,4EAA4E;IAC5E,6CAA6C;IAC7C,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IACjF,8EAA8E;IAC9E,gBAAgB;IAChB,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC;IAC/E,OAAO,UAAU,SAAS,IAAI,IAAI,EAAE,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,UAAkB,EAClB,WAAgC,EAChC,MAAc;IAEd,IAAI,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,WAAW;QAAE,OAAO;IACnE,MAAM,IAAI,KAAK,CACb,uCAAuC,IAAI,UAAU,UAAU,4DAA4D,MAAM,EAAE,CACpI,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAwB,EAAE,MAAc,EAAE,OAAgB;IACjF,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,iCAAiC,EAAE,CAAC,CAAC;IAC7E,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAwB,EACxB,GAAW,EACX,OAAe;IAEf,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,QAAQ,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,GAAG,IAAI,iBAAiB,EAAE,CAAC,CAAC;IACjE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAA8B,EAC9B,SAAiB,EACjB,aAAa,GAAG,KAAK;IAErB,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,4DAA4D;IAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,uEAAuE;IACvE,oDAAoD;IACpD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,+EAA+E;IAC/E,aAAa;IACb,IAAI,aAAa;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,IAAI,KAAK,aAAa,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,WAAqB;IAC3E,IAAI,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAC,MAAmB,EAAE,IAAY,EAAE,IAAY;IACxE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE;YAC7B,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YAChD,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,GAAG,EAAE;YACvB,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxC,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAmB,EACnB,QAAgB,EAChB,IAAY,EACZ,WAAW,GAAG,GAAG;IAEjB,IAAI,IAAI,GAAG,QAAQ,CAAC;IACpB,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM;QACR,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,CAAC,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;gBAChG,IAAI,EAAE,CAAC;gBACP,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,kEAAkE;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACjC,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB,CAChC,GAAW,EACX,QAAQ,GAAoB,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,aAAa,GAAG,GAAG,CAAC;IACrD,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,GAAG,GAAG,CAAC;IAClD,OAAO,aAAa,GAAG,GAAG,CAAC;AAC7B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,4EAA4E;IAC5E,0EAA0E;IAC1E,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;QAC3D,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,IAAI,CAAC,2CAA2C,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,31 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Markdown → HTML for the dashboard's `/api/render
|
|
2
|
+
* Markdown → HTML for the dashboard's `/api/render`, and a trust boundary rather
|
|
3
|
+
* than a formatting detail: the output is assigned with `innerHTML`, so it runs
|
|
4
|
+
* in the same origin that answers `POST /api/task`. The CSRF defence on
|
|
5
|
+
* `handleTaskUpdate` only stops *cross-origin* callers, so a handler smuggled in
|
|
6
|
+
* through a markdown file would sit inside it.
|
|
3
7
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* defence documented on `handleTaskUpdate` only stops *cross-origin* callers, so
|
|
8
|
-
* a handler smuggled in through a markdown file would sit on the inside of it.
|
|
9
|
-
*
|
|
10
|
-
* Raw HTML is escaped rather than allowlisted. An allowlist has to be kept
|
|
11
|
-
* ahead of every attribute and scheme that can execute, and the documents this
|
|
12
|
-
* renders — proposals, specs, tasks, ADRs — have no reason to carry markup that
|
|
13
|
-
* markdown cannot already express. Escaping needs no such upkeep and shows the
|
|
14
|
-
* author exactly what they wrote.
|
|
8
|
+
* Raw HTML is escaped, not allowlisted: an allowlist has to stay ahead of every
|
|
9
|
+
* attribute and scheme that can execute, and these documents need no markup
|
|
10
|
+
* markdown cannot express.
|
|
15
11
|
*/
|
|
16
12
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* Two rules do the work, and both exist because of spellings a naive scheme
|
|
20
|
-
* regex waves through:
|
|
13
|
+
* The URL when it is safe to emit as an attribute, otherwise null. Two rules,
|
|
14
|
+
* both against spellings a naive scheme regex waves through:
|
|
21
15
|
*
|
|
22
|
-
* 1. Tabs and newlines are
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* 2. The scheme comes from `URL`, not from the raw text, so case variants and
|
|
28
|
-
* percent-encoded forms normalize before they are compared.
|
|
16
|
+
* 1. Tabs and newlines are stripped first. `java	script:alert(1)` matches no
|
|
17
|
+
* `^javascript:` regex, but the URL parser — and the browser — strips them
|
|
18
|
+
* and is left with `javascript:`.
|
|
19
|
+
* 2. The scheme comes from `URL`, not the raw text, so case variants and
|
|
20
|
+
* percent-encoded forms normalize before comparison.
|
|
29
21
|
*/
|
|
30
22
|
export declare function safeUrl(href: string): string | null;
|
|
31
23
|
/** Renders markdown to HTML with raw HTML escaped and URL schemes restricted. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-render.d.ts","sourceRoot":"","sources":["../../src/core/markdown-render.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"markdown-render.d.ts","sourceRoot":"","sources":["../../src/core/markdown-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6BH;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAenD;AA+BD,iFAAiF;AACjF,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E"}
|
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Markdown → HTML for the dashboard's `/api/render
|
|
2
|
+
* Markdown → HTML for the dashboard's `/api/render`, and a trust boundary rather
|
|
3
|
+
* than a formatting detail: the output is assigned with `innerHTML`, so it runs
|
|
4
|
+
* in the same origin that answers `POST /api/task`. The CSRF defence on
|
|
5
|
+
* `handleTaskUpdate` only stops *cross-origin* callers, so a handler smuggled in
|
|
6
|
+
* through a markdown file would sit inside it.
|
|
3
7
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* defence documented on `handleTaskUpdate` only stops *cross-origin* callers, so
|
|
8
|
-
* a handler smuggled in through a markdown file would sit on the inside of it.
|
|
9
|
-
*
|
|
10
|
-
* Raw HTML is escaped rather than allowlisted. An allowlist has to be kept
|
|
11
|
-
* ahead of every attribute and scheme that can execute, and the documents this
|
|
12
|
-
* renders — proposals, specs, tasks, ADRs — have no reason to carry markup that
|
|
13
|
-
* markdown cannot already express. Escaping needs no such upkeep and shows the
|
|
14
|
-
* author exactly what they wrote.
|
|
8
|
+
* Raw HTML is escaped, not allowlisted: an allowlist has to stay ahead of every
|
|
9
|
+
* attribute and scheme that can execute, and these documents need no markup
|
|
10
|
+
* markdown cannot express.
|
|
15
11
|
*/
|
|
16
12
|
import { Marked } from 'marked';
|
|
17
13
|
/**
|
|
18
14
|
* Schemes a link or image may keep. Relative paths and fragments carry no
|
|
19
15
|
* scheme and are allowed by falling through the `URL` parse below.
|
|
20
16
|
*
|
|
21
|
-
* `data:` is excluded
|
|
22
|
-
*
|
|
17
|
+
* `data:` is excluded: `data:text/html` navigates to attacker markup in this
|
|
18
|
+
* origin, and no spec document needs an inline blob.
|
|
23
19
|
*/
|
|
24
20
|
const SAFE_URL_SCHEMES = new Set(['http:', 'https:', 'mailto:']);
|
|
25
21
|
function escapeHtml(text) {
|
|
@@ -31,29 +27,24 @@ function escapeHtml(text) {
|
|
|
31
27
|
.replace(/'/g, ''');
|
|
32
28
|
}
|
|
33
29
|
/**
|
|
34
|
-
* Base for resolving relative hrefs
|
|
35
|
-
* `parsed.protocol` lands in the allowlist and
|
|
36
|
-
*
|
|
37
|
-
* original (stripped) text is returned.
|
|
30
|
+
* Base for resolving relative hrefs: a relative URL inherits this scheme, so
|
|
31
|
+
* `parsed.protocol` lands in the allowlist and one check covers both absolute
|
|
32
|
+
* and relative inputs. The host is never emitted.
|
|
38
33
|
*/
|
|
39
34
|
const RELATIVE_BASE = 'https://tospec.invalid/';
|
|
40
35
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* Two rules do the work, and both exist because of spellings a naive scheme
|
|
44
|
-
* regex waves through:
|
|
36
|
+
* The URL when it is safe to emit as an attribute, otherwise null. Two rules,
|
|
37
|
+
* both against spellings a naive scheme regex waves through:
|
|
45
38
|
*
|
|
46
|
-
* 1. Tabs and newlines are
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* 2. The scheme comes from `URL`, not from the raw text, so case variants and
|
|
52
|
-
* percent-encoded forms normalize before they are compared.
|
|
39
|
+
* 1. Tabs and newlines are stripped first. `java	script:alert(1)` matches no
|
|
40
|
+
* `^javascript:` regex, but the URL parser — and the browser — strips them
|
|
41
|
+
* and is left with `javascript:`.
|
|
42
|
+
* 2. The scheme comes from `URL`, not the raw text, so case variants and
|
|
43
|
+
* percent-encoded forms normalize before comparison.
|
|
53
44
|
*/
|
|
54
45
|
export function safeUrl(href) {
|
|
55
|
-
//
|
|
56
|
-
//
|
|
46
|
+
// The same normalization the URL parser applies: C0 controls and space
|
|
47
|
+
// trimmed from both ends, tab/LF/CR removed throughout.
|
|
57
48
|
const cleaned = href.replace(/[\x00- ]+$/, '').replace(/^[\x00- ]+/, '').replace(/[\t\n\r]/g, '');
|
|
58
49
|
if (cleaned === '')
|
|
59
50
|
return null;
|
|
@@ -67,7 +58,7 @@ export function safeUrl(href) {
|
|
|
67
58
|
if (!SAFE_URL_SCHEMES.has(parsed.protocol))
|
|
68
59
|
return null;
|
|
69
60
|
// The cleaned form, not the input: what was validated has to be what is
|
|
70
|
-
// emitted, or the browser re-reads characters
|
|
61
|
+
// emitted, or the browser re-reads the characters removed above.
|
|
71
62
|
return cleaned;
|
|
72
63
|
}
|
|
73
64
|
const renderer = new Marked({
|
|
@@ -79,8 +70,8 @@ const renderer = new Marked({
|
|
|
79
70
|
link(token) {
|
|
80
71
|
const body = this.parser.parseInline(token.tokens);
|
|
81
72
|
const href = safeUrl(token.href);
|
|
82
|
-
// A rejected scheme keeps the text and loses the link
|
|
83
|
-
//
|
|
73
|
+
// A rejected scheme keeps the text and loses the link; dropping the node
|
|
74
|
+
// would hide that the author wrote something the renderer refused.
|
|
84
75
|
if (href === null)
|
|
85
76
|
return body;
|
|
86
77
|
const title = token.title ? ` title="${escapeHtml(token.title)}"` : '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-render.js","sourceRoot":"","sources":["../../src/core/markdown-render.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"markdown-render.js","sourceRoot":"","sources":["../../src/core/markdown-render.ts"],"names":[],"mappings":"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"}
|
package/dist/core/migrate.d.ts
CHANGED
|
@@ -21,18 +21,18 @@ export interface MigrateSummary {
|
|
|
21
21
|
context: 'carried' | 'conflict' | 'empty' | 'absent';
|
|
22
22
|
/** REMOVED requirements dropped during main-spec normalization (`spec/name`). */
|
|
23
23
|
removedRequirements: string[];
|
|
24
|
-
/** RENAMED
|
|
24
|
+
/** Renames a RENAMED section asked for and normalization applied (`spec/from -> to`). */
|
|
25
|
+
renamedRequirements: string[];
|
|
26
|
+
/**
|
|
27
|
+
* RENAMED entries normalization could not act on, so the old name stands
|
|
28
|
+
* (`spec/name`). Reported for manual review rather than dropped.
|
|
29
|
+
*/
|
|
25
30
|
renamedKept: string[];
|
|
26
31
|
}
|
|
27
32
|
export declare class MigrateError extends Error {
|
|
28
33
|
/**
|
|
29
|
-
* A full `CommandDiagnostic
|
|
30
|
-
*
|
|
31
|
-
* `asStatus` recognises an error's diagnostic by `typeof diagnostic.code ===
|
|
32
|
-
* 'string'`, so the partial shape failed that test and every migrate failure
|
|
33
|
-
* fell through to the generic branch — which builds a status entry from the
|
|
34
|
-
* message alone. The `fix` was constructed at each throw site and then
|
|
35
|
-
* silently discarded on the way out.
|
|
34
|
+
* A full `CommandDiagnostic`: `asStatus` recognises one by `typeof
|
|
35
|
+
* diagnostic.code === 'string'`, so a bare `{ fix }` is dropped.
|
|
36
36
|
*/
|
|
37
37
|
readonly diagnostic: CommandDiagnostic;
|
|
38
38
|
constructor(message: string, options?: {
|
|
@@ -42,9 +42,8 @@ export declare class MigrateError extends Error {
|
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Converts an OpenSpec archive dir name (`YYYY-MM-DD-<name>`) to the tospec
|
|
45
|
-
* stamp form (`YYYYMMDD_000000-<name>`). OpenSpec only recorded the date, so
|
|
46
|
-
*
|
|
47
|
-
* unchanged (they already parse as `<stamp>-<name>` no worse than before).
|
|
45
|
+
* stamp form (`YYYYMMDD_000000-<name>`). OpenSpec only recorded the date, so the
|
|
46
|
+
* time part is zero-filled. Names without the date prefix pass through.
|
|
48
47
|
*/
|
|
49
48
|
export declare function convertArchiveDirName(dirName: string): string;
|
|
50
49
|
/**
|
|
@@ -57,7 +56,12 @@ export declare function normalizeMainSpec(content: string, capabilityName: strin
|
|
|
57
56
|
fixed: 'delta' | 'headerless';
|
|
58
57
|
/** Names of requirements a REMOVED section dropped (recorded, not silent). */
|
|
59
58
|
removed: string[];
|
|
60
|
-
/**
|
|
59
|
+
/** Renames a RENAMED section asked for and this rebuild applied. */
|
|
60
|
+
renamed: Array<{
|
|
61
|
+
from: string;
|
|
62
|
+
to: string;
|
|
63
|
+
}>;
|
|
64
|
+
/** RENAMED entries nothing could be applied for; the old name stands. */
|
|
61
65
|
renamedKept: string[];
|
|
62
66
|
} | null;
|
|
63
67
|
export declare class MigrateCommand {
|
|
@@ -73,10 +77,9 @@ export declare class MigrateCommand {
|
|
|
73
77
|
*/
|
|
74
78
|
private migrateMetadata;
|
|
75
79
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* replaces its counterpart. Reuses archive's EPERM/EXDEV-safe move helpers.
|
|
80
|
+
* Promotes the built staging tree into the target: one move when the target is
|
|
81
|
+
* absent, else entry-by-entry replacement into the content-free tospec/ that
|
|
82
|
+
* `tospec init` leaves. Uses archive's EPERM/EXDEV-safe helpers.
|
|
80
83
|
*/
|
|
81
84
|
private promoteStaging;
|
|
82
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/core/migrate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/core/migrate.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAkCnF,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,kFAAkF;AAClF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAiC,CAAC;AAE9F,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IACvG,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,kDAAkD;IAClD,OAAO,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrD,iFAAiF;IACjF,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,yFAAyF;IACzF,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAEvC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EASrE;CACF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GACrB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9B,8EAA8E;IAC9E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oEAAoE;IACpE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,GAAG,IAAI,CAqFP;AAqED,qBAAa,cAAc;IACnB,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAsLzE;IAED,mGAAmG;YACrF,aAAa;IA6B3B;;;;;;OAMG;YACW,eAAe;IAe7B;;;;OAIG;YACW,cAAc;CAiB7B"}
|