@danmoisan/drm-copilot-mcp 1.1.23 → 1.1.24
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/out/mcp-server.js +13347 -7926
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/discovery-capability-sentinel.md +34 -0
- package/resources/claude-customizations/.claude/agents/legacy-parity-analyst.md +101 -43
- package/resources/claude-customizations/.claude/agents/migration-coverage-reviewer.md +107 -43
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +14 -0
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +21 -1
- package/resources/claude-customizations/.claude/agents/pr-author.md +17 -1
- package/resources/claude-customizations/.claude/agents/requirements-reconciler.md +117 -42
- package/resources/claude-customizations/.claude/agents/runtime-characterization-analyst.md +103 -43
- package/resources/claude-customizations/.claude/hooks/discovery-capability-probe.ps1 +102 -0
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +69 -194
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-planning-gate.ps1 +87 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +6 -3
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +168 -48
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +1 -1
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +59 -20
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +44 -3
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +60 -4
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +4 -2
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +59 -20
- package/resources/claude-customizations/.claude/hooks/record-discovery-agent-start.ps1 +132 -0
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +56 -212
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-rejection.ps1 +172 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +9 -1
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +9 -3
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusAggregate.psm1 +154 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusCombination.psm1 +228 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +1 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusNormalization.psm1 +4 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +63 -16
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +56 -1
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +4 -1
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +5 -1
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +25 -2
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +188 -341
- package/resources/claude-customizations/.claude/lib/worktree-resolution/HookTargetWorktree.psm1 +391 -0
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +1 -0
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +150 -18
- package/resources/claude-customizations/.claude/settings.json +32 -3
- package/resources/claude-customizations/.claude/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/claude-customizations/.claude/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/claude-customizations/.claude/skills/discovery-behavior-reconciliation/SKILL.md +28 -47
- package/resources/claude-customizations/.claude/skills/discovery-coverage-ledger/SKILL.md +32 -48
- package/resources/claude-customizations/.claude/skills/discovery-parity-matrix/SKILL.md +28 -45
- package/resources/claude-customizations/.claude/skills/discovery-repo-inventory/SKILL.md +28 -62
- package/resources/claude-customizations/.claude/skills/discovery-runtime-characterization/SKILL.md +28 -45
- package/resources/claude-customizations/.claude/skills/discovery-validate-artifacts/SKILL.md +28 -61
- package/resources/claude-customizations/.claude/skills/discovery-workflow/SKILL.md +55 -139
- package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +24 -9
- package/resources/claude-customizations/.claude/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/claude-customizations/.claude/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/claude-customizations/.claude/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +5 -4
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +21 -1
- package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +11 -1
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +34 -0
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +69 -6
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/parallel-run/SKILL.md +6 -0
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +21 -4
- package/resources/claude-customizations/.claude/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/claude-customizations/.claude/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/claude-customizations/config/blast-radius.json +6 -5
- package/resources/claude-customizations/config/orchestration-routing.json +61 -1
- package/resources/claude-customizations/pack-manifests/core.json +33 -1
- package/resources/codex-and-agents-customizations/.agents/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +7 -0
- package/resources/codex-and-agents-customizations/.agents/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-coverage-ledger/SKILL.md +50 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-parity-matrix/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-repo-inventory/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-runtime-characterization/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-validate-artifacts/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-workflow/SKILL.md +62 -0
- package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +24 -9
- package/resources/codex-and-agents-customizations/.agents/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/codex-and-agents-customizations/.agents/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/codex-and-agents-customizations/.agents/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/codex-and-agents-customizations/.agents/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/codex-and-agents-customizations/.codex/agents/discovery-capability-sentinel.toml +51 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c1.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c2.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3-elevated.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c4.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c1.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c2.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3-elevated.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c4.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c1.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c2.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3-elevated.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c4.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c1.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c2.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3-elevated.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c4.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +33 -3
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-agent-profile-attestation.ps1 +22 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/discovery-capability-probe.ps1 +97 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/discovery-start-attestation.ps1 +171 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +4 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-artifact-gate.ps1 +187 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-planning-gate.ps1 +149 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +239 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +6 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +54 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +54 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-target-worktree.ps1 +369 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/record-subagent-routing-attestation.ps1 +8 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +22 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-discovery-agent-output.ps1 +178 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +11 -1
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +63 -1
- package/resources/config/orchestration-routing.json +61 -1
- package/resources/customizations/.github/agents/discovery-capability-sentinel.agent.md +34 -0
- package/resources/customizations/.github/agents/legacy-parity-analyst.agent.md +122 -0
- package/resources/customizations/.github/agents/migration-coverage-reviewer.agent.md +128 -0
- package/resources/customizations/.github/agents/requirements-reconciler.agent.md +138 -0
- package/resources/customizations/.github/agents/runtime-characterization-analyst.agent.md +124 -0
- package/resources/customizations/.github/hooks/discovery-agent-start.ps1 +139 -0
- package/resources/customizations/.github/hooks/discovery-agent-stop.ps1 +123 -0
- package/resources/customizations/.github/hooks/discovery-capability-probe.ps1 +98 -0
- package/resources/customizations/.github/hooks/discovery-planning.ps1 +91 -0
- package/resources/customizations/.github/hooks/discovery-pre-tool.ps1 +123 -0
- package/resources/customizations/.github/hooks/discovery.json +35 -0
- package/resources/customizations/.github/instructions/mermaid.instructions.md +85 -0
- package/resources/customizations/.github/prompts/execute-hard-lock.prompt.md +105 -0
- package/resources/customizations/.github/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/customizations/.github/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/customizations/.github/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-coverage-ledger/SKILL.md +50 -0
- package/resources/customizations/.github/skills/discovery-parity-matrix/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-repo-inventory/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-runtime-characterization/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-validate-artifacts/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-workflow/SKILL.md +62 -0
- package/resources/customizations/.github/skills/execution-environment/SKILL.md +24 -9
- package/resources/customizations/.github/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/customizations/.github/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/customizations/.github/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/customizations/.github/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/customizations/.github/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/customizations/.github/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/customizations/.github/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/lib/codex-routing/CodexDeployment.psm1 +5 -1
- package/resources/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
- package/resources/lib/codex-routing/CodexTopology.psm1 +25 -2
- package/resources/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
- package/resources/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
- package/resources/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
- package/resources/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
- package/resources/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
- package/resources/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
- package/resources/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
- package/resources/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
- package/resources/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
- package/resources/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
- package/resources/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
- package/resources/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
- package/resources/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
- package/resources/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
- package/resources/powershell/PoshQC/PoshQC.Parallel.psm1 +452 -0
- package/resources/powershell/PoshQC/PoshQC.Shard.psm1 +106 -8
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +12 -0
- package/resources/powershell/PoshQC/PoshQC.psd1 +6 -1
- package/resources/powershell/PoshQC/PoshQC.psm1 +7 -1
- package/resources/powershell/PoshQC/README.md +20 -1
package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1
CHANGED
|
@@ -1,61 +1,41 @@
|
|
|
1
1
|
<#
|
|
2
2
|
.SYNOPSIS
|
|
3
|
-
|
|
3
|
+
Bounded compatibility surface of the retired PowerShell discovery-artifact validator (#475, #980).
|
|
4
4
|
.DESCRIPTION
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
the
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
Until issue #980 this module evaluated discovery artifacts itself: a placeholder
|
|
6
|
+
profile contract and `Test-Json -SchemaFile` checks against the v1 schemas. One
|
|
7
|
+
Python engine now owns artifact meaning, the installed TypeScript gateway is the
|
|
8
|
+
only writer of protected validation receipts, and the native hooks under
|
|
9
|
+
`.claude/hooks`, `.codex/hooks` and `.github/hooks` verify protected current
|
|
10
|
+
authority through the sibling Discovery* modules. This module therefore keeps
|
|
11
|
+
its exported names for compatibility and directs every semantic question to
|
|
12
|
+
the authoritative service:
|
|
13
|
+
|
|
14
|
+
- the artifact-type table and the destination PowerShell floor are retained
|
|
15
|
+
(the floor is still the hook runtime requirement, and an unsupported host
|
|
16
|
+
fails closed with the same actionable message);
|
|
17
|
+
- every former validation entry returns a validation-required result naming
|
|
18
|
+
`validate_discovery_artifacts`; none parses a profile or a schema, none
|
|
19
|
+
returns an empty error list, and `Invoke-DiscoveryArtifactValidation` never
|
|
20
|
+
returns `ExitCode = 0`, so an old entry name cannot mint a passing gate;
|
|
21
|
+
- `Get-DiscoveryValidationAuthority` reports whether the workspace holds a
|
|
22
|
+
protected activation on a supported host, which is the only authority a
|
|
23
|
+
native hook consults.
|
|
24
|
+
|
|
25
|
+
No Python interpreter or other process is invoked anywhere in this module.
|
|
24
26
|
.NOTES
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
RESULT CONTRACT (defect D-2 avoidance). Success is SILENT: a passing validation
|
|
28
|
-
returns `ExitCode = 0` with EMPTY `Output`. Both hooks deny on a non-zero exit code
|
|
29
|
-
OR on non-empty output, so the previous Python CLI's success line
|
|
30
|
-
("<type> validation passed: <path>") turned a PASSING validation into a DENY.
|
|
31
|
-
|
|
32
|
-
PARITY with `validate_discovery_profile.py` / `validate_discovery_schema_artifacts.py`. Error
|
|
33
|
-
families are preserved: `invalid JSON (...)`, `JSON root must be an object for validation`,
|
|
34
|
-
`schema resolution failed (...)`, `Profile document is empty.`,
|
|
35
|
-
`Profile document root must be a mapping.`, `Missing required field: <field>.` Schema
|
|
36
|
-
location resolves solely from each artifact's own `$schema`, as in the reference; the
|
|
37
|
-
type-to-file table below is documentation and artifact-type validation only. Deliberate
|
|
38
|
-
divergences: an `http(s)://` `$schema` is NOT fetched (no guaranteed destination network,
|
|
39
|
-
so a non-`file` scheme is reported fail-closed in the `schema resolution failed (...)`
|
|
40
|
-
family), and `file://` resolves through `[uri]::LocalPath` rather than the reference's
|
|
41
|
-
`Path(parsed.path)`, which mishandles a Windows `file:///C:/...` path. Unavoidable
|
|
42
|
-
divergence: per-violation wording comes from `Test-Json`, not `jsonschema`, so violation
|
|
43
|
-
strings differ while family and verdict match. The profile check reproduces the
|
|
44
|
-
placeholder contract without a YAML parser (PowerShell ships none); see
|
|
45
|
-
`Get-DiscoveryProfileValidationError` for what is and is not detected.
|
|
46
|
-
.EXAMPLE
|
|
47
|
-
Invoke-DiscoveryArtifactValidation -ValidatorArgs @('evidence-reference', $path)
|
|
48
|
-
|
|
49
|
-
Returns @{ ExitCode = 0; Output = '' } when the artifact conforms.
|
|
27
|
+
Issues #475 and #980. Requires PowerShell 7.4 or later on a destination host.
|
|
50
28
|
CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
|
|
51
29
|
#>
|
|
52
30
|
|
|
53
31
|
Set-StrictMode -Version Latest
|
|
54
32
|
$ErrorActionPreference = 'Stop'
|
|
55
33
|
|
|
34
|
+
Import-Module (Join-Path $PSScriptRoot 'DiscoveryEncoding.psm1') -ErrorAction Stop
|
|
35
|
+
Import-Module (Join-Path $PSScriptRoot 'DiscoveryAuthority.psm1') -ErrorAction Stop
|
|
36
|
+
|
|
56
37
|
# Schema-governed artifact types mapped to their filenames under `schemas/discovery/v1/`.
|
|
57
|
-
#
|
|
58
|
-
# `product-decision`, and `unspecified-behavior` do NOT share their token's stem.
|
|
38
|
+
# Retained as documentation and artifact-type recognition only; no schema is evaluated here.
|
|
59
39
|
$script:DiscoverySchemaArtifactFile = [ordered]@{
|
|
60
40
|
'feature-contract' = 'feature-contract.schema.json'
|
|
61
41
|
'coverage-ledger' = 'coverage-ledger.schema.json'
|
|
@@ -65,47 +45,25 @@ $script:DiscoverySchemaArtifactFile = [ordered]@{
|
|
|
65
45
|
'product-decision' = 'product-decision-record.schema.json'
|
|
66
46
|
'evidence-reference' = 'evidence-reference.schema.json'
|
|
67
47
|
}
|
|
68
|
-
|
|
69
|
-
# `Test-Json -SchemaFile` gained Draft 2020-12 support in PowerShell 7.4 and all seven
|
|
70
|
-
# schemas declare Draft 2020-12, so this floor is unavoidable. Verified on 7.6.3 here.
|
|
71
48
|
$script:MinimumPowerShellVersion = [version]'7.4'
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# `_PLACEHOLDER_REQUIRED_FIELDS` in `validate_discovery_profile.py`, whose own
|
|
75
|
-
# TODO(#9001) marks it as the single seam that changes when #9001 lands.
|
|
76
|
-
$script:ProfileRequiredField = @('legacy_source_path')
|
|
49
|
+
$script:ValidationRequiredPrefix = 'DISCOVERY_VALIDATION_REQUIRED:'
|
|
50
|
+
$script:ServiceOperation = 'validate_discovery_artifacts'
|
|
77
51
|
|
|
78
52
|
function Get-DiscoveryRuntimeVersionError {
|
|
79
53
|
<#
|
|
80
54
|
.SYNOPSIS
|
|
81
|
-
Returns the fail-closed message when the host PowerShell is below 7.4, or
|
|
82
|
-
$null when the host meets the floor.
|
|
55
|
+
Returns the fail-closed message when the host PowerShell is below 7.4, or $null when the host meets the floor.
|
|
83
56
|
.DESCRIPTION
|
|
84
|
-
The destination version floor (issue #475)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
This runs BEFORE any schema validation so an unsupported host fails with one
|
|
89
|
-
explicit, actionable message instead of a raw `Test-Json` parameter error. It
|
|
90
|
-
never degrades silently: no partial validation, no fail-open path.
|
|
91
|
-
|
|
92
|
-
`PowerShellVersion` is the injectable seam, defaulting to the real
|
|
93
|
-
`$PSVersionTable.PSVersion` and only ever READ; nothing here writes
|
|
94
|
-
`$PSVersionTable`, so tests pass a version rather than mutating host state.
|
|
95
|
-
.OUTPUTS
|
|
96
|
-
[string] The fail-closed message, or $null when the host is supported.
|
|
57
|
+
The destination version floor (issue #475) is unchanged: the native hooks
|
|
58
|
+
and this module require PowerShell 7.4 or later. `PowerShellVersion` is the
|
|
59
|
+
injectable seam, defaulting to the real `$PSVersionTable.PSVersion` and only
|
|
60
|
+
ever read.
|
|
97
61
|
#>
|
|
98
62
|
[CmdletBinding()]
|
|
99
63
|
[OutputType([string])]
|
|
100
|
-
param(
|
|
101
|
-
[Parameter(Mandatory = $false)]
|
|
102
|
-
[version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
if ($PowerShellVersion -ge $script:MinimumPowerShellVersion) {
|
|
106
|
-
return $null
|
|
107
|
-
}
|
|
64
|
+
param([Parameter(Mandatory = $false)][version]$PowerShellVersion = $PSVersionTable.PSVersion)
|
|
108
65
|
|
|
66
|
+
if ($PowerShellVersion -ge $script:MinimumPowerShellVersion) { return $null }
|
|
109
67
|
return (
|
|
110
68
|
"Discovery-artifact validation requires PowerShell $($script:MinimumPowerShellVersion) or later " +
|
|
111
69
|
"(this host is PowerShell $PowerShellVersion). Reason: schema validation uses " +
|
|
@@ -118,302 +76,167 @@ function Get-DiscoveryRuntimeVersionError {
|
|
|
118
76
|
function Get-DiscoverySchemaArtifactType {
|
|
119
77
|
<#
|
|
120
78
|
.SYNOPSIS
|
|
121
|
-
Returns the seven schema-governed artifact-type tokens
|
|
79
|
+
Returns the seven schema-governed artifact-type tokens.
|
|
122
80
|
#>
|
|
123
81
|
[CmdletBinding()]
|
|
124
|
-
[OutputType([
|
|
82
|
+
[OutputType([string[]])]
|
|
125
83
|
param()
|
|
126
84
|
|
|
127
|
-
return
|
|
85
|
+
return [string[]]@($script:DiscoverySchemaArtifactFile.Keys)
|
|
128
86
|
}
|
|
129
87
|
|
|
130
88
|
function Get-DiscoverySchemaFileName {
|
|
131
89
|
<#
|
|
132
90
|
.SYNOPSIS
|
|
133
|
-
Returns the schema filename
|
|
134
|
-
when the token is not a schema-governed type. Documentation and artifact-type
|
|
135
|
-
validation only: schema RESOLUTION is driven by the artifact's `$schema`.
|
|
91
|
+
Returns the v1 schema filename of a schema-governed artifact type, or $null for any other token.
|
|
136
92
|
#>
|
|
137
93
|
[CmdletBinding()]
|
|
138
94
|
[OutputType([string])]
|
|
139
|
-
param(
|
|
140
|
-
[Parameter(Mandatory = $true)]
|
|
141
|
-
[AllowEmptyString()]
|
|
142
|
-
[string]$ArtifactType
|
|
143
|
-
)
|
|
95
|
+
param([Parameter(Mandatory = $true)][AllowEmptyString()][string]$ArtifactType)
|
|
144
96
|
|
|
145
|
-
if ($script:DiscoverySchemaArtifactFile.Contains($ArtifactType)) {
|
|
146
|
-
return [string]$script:DiscoverySchemaArtifactFile[$ArtifactType]
|
|
147
|
-
}
|
|
97
|
+
if ($script:DiscoverySchemaArtifactFile.Contains($ArtifactType)) { return [string]$script:DiscoverySchemaArtifactFile[$ArtifactType] }
|
|
148
98
|
return $null
|
|
149
99
|
}
|
|
150
100
|
|
|
151
|
-
function
|
|
101
|
+
function Resolve-DiscoverySchemaFilePath {
|
|
152
102
|
<#
|
|
153
103
|
.SYNOPSIS
|
|
154
|
-
|
|
155
|
-
inspection, without a YAML parser.
|
|
104
|
+
Returns the repository path of a schema-governed artifact type's v1 schema file, or $null.
|
|
156
105
|
.DESCRIPTION
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
therefore ignored, which is exactly the scope the placeholder contract needs.
|
|
160
|
-
Returns $null when the document presents no top-level mapping key, which the
|
|
161
|
-
caller reports as a non-mapping root.
|
|
106
|
+
Documentation lookup only; the schema is never evaluated here. Artifact
|
|
107
|
+
`$schema` references are not resolved or fetched by this module any more.
|
|
162
108
|
#>
|
|
163
109
|
[CmdletBinding()]
|
|
164
|
-
[OutputType([
|
|
110
|
+
[OutputType([string])]
|
|
165
111
|
param(
|
|
166
|
-
[Parameter(Mandatory = $true)]
|
|
167
|
-
[
|
|
168
|
-
[string]$Text
|
|
112
|
+
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$ArtifactType,
|
|
113
|
+
[Parameter(Mandatory = $true)][string]$RepositoryRoot
|
|
169
114
|
)
|
|
170
115
|
|
|
171
|
-
$
|
|
172
|
-
$
|
|
173
|
-
|
|
174
|
-
foreach ($line in ($Text -split '\r?\n')) {
|
|
175
|
-
$trimmed = $line.Trim()
|
|
176
|
-
if ($trimmed.Length -eq 0 -or $trimmed.StartsWith('#')) {
|
|
177
|
-
continue
|
|
178
|
-
}
|
|
179
|
-
if ($trimmed -eq '---' -or $trimmed -eq '...') {
|
|
180
|
-
continue
|
|
181
|
-
}
|
|
182
|
-
$sawContent = $true
|
|
183
|
-
|
|
184
|
-
# Only unindented lines can carry a top-level key.
|
|
185
|
-
if ($line -match '^(?<key>[A-Za-z_][A-Za-z0-9_.-]*)\s*:(\s|$)') {
|
|
186
|
-
$keys.Add($Matches['key'])
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
# Content that never presented an unindented `key:` is not a mapping root
|
|
191
|
-
# (a sequence root, a bare scalar, or a flow document).
|
|
192
|
-
if (-not $sawContent -or $keys.Count -eq 0) {
|
|
193
|
-
return $null
|
|
194
|
-
}
|
|
195
|
-
return , $keys.ToArray()
|
|
116
|
+
$fileName = Get-DiscoverySchemaFileName -ArtifactType $ArtifactType
|
|
117
|
+
if ($null -eq $fileName) { return $null }
|
|
118
|
+
return "$($RepositoryRoot.TrimEnd('/', '\'))/schemas/discovery/v1/$fileName"
|
|
196
119
|
}
|
|
197
120
|
|
|
198
|
-
function Get-
|
|
121
|
+
function Get-DiscoveryValidationRequiredMessage {
|
|
199
122
|
<#
|
|
200
123
|
.SYNOPSIS
|
|
201
|
-
|
|
202
|
-
mirroring `validate_profile_text` in `validate_discovery_profile.py`.
|
|
203
|
-
.DESCRIPTION
|
|
204
|
-
Reproduced checks: empty/whitespace-only document; non-mapping root; and the
|
|
205
|
-
placeholder required-field set (`legacy_source_path`), reported one error per
|
|
206
|
-
absent field.
|
|
207
|
-
|
|
208
|
-
NOT reproduced: detection of arbitrary YAML syntax errors. PowerShell ships no
|
|
209
|
-
YAML parser and this module must not add a dependency, so the reference's
|
|
210
|
-
`Profile document is not valid YAML: <exc>` branch has no direct analogue. The
|
|
211
|
-
substitute is fail-CLOSED: any document not presenting an unindented `key:`
|
|
212
|
-
line is reported as a non-mapping root rather than accepted, so a malformed
|
|
213
|
-
document is still rejected and only the diagnostic wording differs.
|
|
214
|
-
.OUTPUTS
|
|
215
|
-
[object[]] Zero or more error strings; empty when the document conforms.
|
|
124
|
+
Returns the validation-required message that directs an artifact question to the authoritative service.
|
|
216
125
|
#>
|
|
217
126
|
[CmdletBinding()]
|
|
218
|
-
[OutputType([
|
|
127
|
+
[OutputType([string])]
|
|
219
128
|
param(
|
|
220
|
-
[Parameter(Mandatory = $
|
|
221
|
-
[AllowEmptyString()]
|
|
222
|
-
[string]$Text,
|
|
223
|
-
|
|
224
|
-
[Parameter(Mandatory = $false)]
|
|
225
|
-
[version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
129
|
+
[Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$ArtifactType = $null,
|
|
130
|
+
[Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$Path = $null
|
|
226
131
|
)
|
|
227
132
|
|
|
228
|
-
$
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if ($null -ne $versionError) {
|
|
234
|
-
$errors.Add($versionError)
|
|
235
|
-
return , $errors.ToArray()
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if ([string]::IsNullOrWhiteSpace($Text)) {
|
|
239
|
-
$errors.Add('Profile document is empty.')
|
|
240
|
-
return , $errors.ToArray()
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
$keys = Get-DiscoveryProfileTopLevelKey -Text $Text
|
|
244
|
-
if ($null -eq $keys) {
|
|
245
|
-
$errors.Add('Profile document root must be a mapping.')
|
|
246
|
-
return , $errors.ToArray()
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
# Report every absent field so a maintainer can fix the document in one pass.
|
|
250
|
-
foreach ($field in $script:ProfileRequiredField) {
|
|
251
|
-
if ($keys -notcontains $field) {
|
|
252
|
-
$errors.Add("Missing required field: $field.")
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return , $errors.ToArray()
|
|
133
|
+
$subject = $(if ([string]::IsNullOrWhiteSpace($ArtifactType)) { 'the artifact' } else { "the $ArtifactType artifact" })
|
|
134
|
+
if (-not [string]::IsNullOrWhiteSpace($Path)) { $subject = "$subject at $Path" }
|
|
135
|
+
return "$($script:ValidationRequiredPrefix) $subject is validated only by the installed discovery service ($($script:ServiceOperation)); " +
|
|
136
|
+
'this compatibility module no longer evaluates profile or schema semantics and cannot authorize a gate. ' +
|
|
137
|
+
'Native hooks verify the protected validation receipt the gateway writes.'
|
|
257
138
|
}
|
|
258
139
|
|
|
259
|
-
function
|
|
140
|
+
function Add-DiscoveryCompatibilityError {
|
|
260
141
|
<#
|
|
261
142
|
.SYNOPSIS
|
|
262
|
-
|
|
143
|
+
Appends the never-empty compatibility errors shared by the retired validation entries to a caller's list.
|
|
263
144
|
.DESCRIPTION
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
.OUTPUTS
|
|
268
|
-
[hashtable] `@{ Path = <string>; Error = <string> }`; exactly one is non-null.
|
|
145
|
+
The version floor is appended alone when the host is below it. Otherwise an
|
|
146
|
+
unrecognized artifact type is appended first (when requested) and the
|
|
147
|
+
validation-required message always follows, so the list is never left empty.
|
|
269
148
|
#>
|
|
270
149
|
[CmdletBinding()]
|
|
271
|
-
[OutputType([
|
|
150
|
+
[OutputType([void])]
|
|
272
151
|
param(
|
|
273
|
-
[Parameter(Mandatory = $true)]
|
|
274
|
-
[AllowNull()]
|
|
275
|
-
[
|
|
152
|
+
[Parameter(Mandatory = $true)][AllowEmptyCollection()][System.Collections.Generic.List[string]]$ErrorList,
|
|
153
|
+
[Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$ArtifactType = $null,
|
|
154
|
+
[Parameter(Mandatory = $false)][version]$PowerShellVersion = $PSVersionTable.PSVersion,
|
|
155
|
+
[Parameter(Mandatory = $false)][switch]$ReportUnrecognizedType
|
|
276
156
|
)
|
|
277
157
|
|
|
278
|
-
|
|
279
|
-
|
|
158
|
+
$floor = Get-DiscoveryRuntimeVersionError -PowerShellVersion $PowerShellVersion
|
|
159
|
+
if ($null -ne $floor) {
|
|
160
|
+
$ErrorList.Add($floor)
|
|
161
|
+
return
|
|
280
162
|
}
|
|
163
|
+
if ($ReportUnrecognizedType) { $ErrorList.Add("Unrecognized discovery artifact type '$ArtifactType'.") }
|
|
164
|
+
$ErrorList.Add((Get-DiscoveryValidationRequiredMessage -ArtifactType $ArtifactType))
|
|
165
|
+
}
|
|
281
166
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
167
|
+
function Get-DiscoveryProfileTopLevelKey {
|
|
168
|
+
<#
|
|
169
|
+
.SYNOPSIS
|
|
170
|
+
Compatibility export: profile parsing is retired, so no top-level key is ever reported.
|
|
171
|
+
#>
|
|
172
|
+
[CmdletBinding()]
|
|
173
|
+
[OutputType([string[]])]
|
|
174
|
+
param([Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text)
|
|
288
175
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
176
|
+
# The text is deliberately not read; the service owns profile semantics.
|
|
177
|
+
$null = $Text
|
|
178
|
+
return [string[]]@()
|
|
179
|
+
}
|
|
293
180
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
181
|
+
function Get-DiscoveryProfileValidationError {
|
|
182
|
+
<#
|
|
183
|
+
.SYNOPSIS
|
|
184
|
+
Returns the version-floor error below PowerShell 7.4, otherwise the validation-required message for the profile.
|
|
185
|
+
#>
|
|
186
|
+
[CmdletBinding()]
|
|
187
|
+
[OutputType([object[]])]
|
|
188
|
+
param(
|
|
189
|
+
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text,
|
|
190
|
+
[Parameter(Mandatory = $false)][version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
191
|
+
)
|
|
299
192
|
|
|
300
|
-
|
|
193
|
+
$null = $Text
|
|
194
|
+
$errors = [System.Collections.Generic.List[string]]::new()
|
|
195
|
+
Add-DiscoveryCompatibilityError -ErrorList $errors -ArtifactType 'profile' -PowerShellVersion $PowerShellVersion
|
|
196
|
+
return , $errors.ToArray()
|
|
301
197
|
}
|
|
302
198
|
|
|
303
199
|
function Get-DiscoverySchemaArtifactValidationError {
|
|
304
200
|
<#
|
|
305
201
|
.SYNOPSIS
|
|
306
|
-
|
|
307
|
-
mirroring `_validate_against_schema` in `validate_discovery_schema_artifacts.py`.
|
|
308
|
-
.DESCRIPTION
|
|
309
|
-
Order of checks, matching the reference: JSON parse, object-root check,
|
|
310
|
-
`$schema` extraction and resolution, then Draft 2020-12 schema validation via
|
|
311
|
-
`Test-Json -SchemaFile`.
|
|
312
|
-
.OUTPUTS
|
|
313
|
-
[object[]] Zero or more error strings; empty when the artifact conforms.
|
|
202
|
+
Returns the version-floor error below PowerShell 7.4, otherwise the validation-required message for a schema-governed artifact.
|
|
314
203
|
#>
|
|
315
204
|
[CmdletBinding()]
|
|
316
205
|
[OutputType([object[]])]
|
|
317
206
|
param(
|
|
318
|
-
[Parameter(Mandatory = $true)]
|
|
319
|
-
[AllowEmptyString()]
|
|
320
|
-
[
|
|
321
|
-
|
|
322
|
-
[Parameter(Mandatory = $false)]
|
|
323
|
-
[version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
207
|
+
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text,
|
|
208
|
+
[Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$ArtifactType = $null,
|
|
209
|
+
[Parameter(Mandatory = $false)][version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
324
210
|
)
|
|
325
211
|
|
|
212
|
+
$null = $Text
|
|
326
213
|
$errors = [System.Collections.Generic.List[string]]::new()
|
|
327
|
-
|
|
328
|
-
# Fail closed before any schema work: on an unsupported host `Test-Json -SchemaFile`
|
|
329
|
-
# would otherwise fail with an opaque parameter error.
|
|
330
|
-
$versionError = Get-DiscoveryRuntimeVersionError -PowerShellVersion $PowerShellVersion
|
|
331
|
-
if ($null -ne $versionError) {
|
|
332
|
-
$errors.Add($versionError)
|
|
333
|
-
return , $errors.ToArray()
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
$parsed = $null
|
|
337
|
-
try {
|
|
338
|
-
$parsed = ConvertFrom-Json -InputObject $Text -Depth 100 -ErrorAction Stop
|
|
339
|
-
}
|
|
340
|
-
catch {
|
|
341
|
-
$errors.Add("invalid JSON ($($_.Exception.Message))")
|
|
342
|
-
return , $errors.ToArray()
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if ($parsed -isnot [System.Management.Automation.PSCustomObject]) {
|
|
346
|
-
$errors.Add('JSON root must be an object for validation')
|
|
347
|
-
return , $errors.ToArray()
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
$schemaProperty = $parsed.PSObject.Properties['$schema']
|
|
351
|
-
$schemaUri = if ($null -eq $schemaProperty) { $null } else { $schemaProperty.Value }
|
|
352
|
-
|
|
353
|
-
$resolution = Resolve-DiscoverySchemaFilePath -SchemaUri $schemaUri
|
|
354
|
-
if ($null -ne $resolution.Error) {
|
|
355
|
-
$errors.Add([string]$resolution.Error)
|
|
356
|
-
return , $errors.ToArray()
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
# Test-Json emits one non-terminating error per schema violation; collect them
|
|
360
|
-
# all rather than stopping at the first, matching the reference's behavior.
|
|
361
|
-
$schemaErrors = $null
|
|
362
|
-
$isValid = Test-Json -Json $Text -SchemaFile ([string]$resolution.Path) `
|
|
363
|
-
-ErrorAction SilentlyContinue -ErrorVariable schemaErrors
|
|
364
|
-
if (-not $isValid) {
|
|
365
|
-
foreach ($schemaError in @($schemaErrors)) {
|
|
366
|
-
$errors.Add([string]$schemaError.Exception.Message)
|
|
367
|
-
}
|
|
368
|
-
# Guarantee a non-empty result so a failure is never reported as a pass.
|
|
369
|
-
if ($errors.Count -eq 0) {
|
|
370
|
-
$errors.Add('JSON is not valid with the schema')
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
214
|
+
Add-DiscoveryCompatibilityError -ErrorList $errors -ArtifactType $ArtifactType -PowerShellVersion $PowerShellVersion
|
|
374
215
|
return , $errors.ToArray()
|
|
375
216
|
}
|
|
376
217
|
|
|
377
218
|
function Get-DiscoveryArtifactValidationError {
|
|
378
219
|
<#
|
|
379
220
|
.SYNOPSIS
|
|
380
|
-
|
|
221
|
+
Returns the compatibility error list for an artifact: the floor, an unrecognized type, and always the validation-required message.
|
|
381
222
|
.DESCRIPTION
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
.OUTPUTS
|
|
386
|
-
[object[]] Zero or more error strings; empty when the artifact conforms.
|
|
223
|
+
The list is never empty. The version floor is reported alone when the host is
|
|
224
|
+
below it; otherwise an unrecognized artifact type is reported before the
|
|
225
|
+
validation-required message so the caller sees both defects.
|
|
387
226
|
#>
|
|
388
227
|
[CmdletBinding()]
|
|
389
228
|
[OutputType([object[]])]
|
|
390
229
|
param(
|
|
391
|
-
[Parameter(Mandatory = $true)]
|
|
392
|
-
[AllowEmptyString()]
|
|
393
|
-
[
|
|
394
|
-
|
|
395
|
-
[Parameter(Mandatory = $true)]
|
|
396
|
-
[AllowEmptyString()]
|
|
397
|
-
[string]$Text,
|
|
398
|
-
|
|
399
|
-
[Parameter(Mandatory = $false)]
|
|
400
|
-
[version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
230
|
+
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$ArtifactType,
|
|
231
|
+
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text,
|
|
232
|
+
[Parameter(Mandatory = $false)][version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
401
233
|
)
|
|
402
234
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
return , $profileErrors
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
if ($script:DiscoverySchemaArtifactFile.Contains($ArtifactType)) {
|
|
412
|
-
$schemaErrors = Get-DiscoverySchemaArtifactValidationError -Text $Text -PowerShellVersion $PowerShellVersion
|
|
413
|
-
return , $schemaErrors
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
return , @("Unsupported artifact type: $ArtifactType")
|
|
235
|
+
$null = $Text
|
|
236
|
+
$unrecognized = ($ArtifactType -ne 'profile' -and $null -eq (Get-DiscoverySchemaFileName -ArtifactType $ArtifactType))
|
|
237
|
+
$errors = [System.Collections.Generic.List[string]]::new()
|
|
238
|
+
Add-DiscoveryCompatibilityError -ErrorList $errors -ArtifactType $ArtifactType -PowerShellVersion $PowerShellVersion -ReportUnrecognizedType:$unrecognized
|
|
239
|
+
return , $errors.ToArray()
|
|
417
240
|
}
|
|
418
241
|
|
|
419
242
|
function ConvertTo-DiscoveryValidationResult {
|
|
@@ -421,69 +244,91 @@ function ConvertTo-DiscoveryValidationResult {
|
|
|
421
244
|
.SYNOPSIS
|
|
422
245
|
Shapes an error list into the hook seam's `@{ ExitCode; Output }` result.
|
|
423
246
|
.DESCRIPTION
|
|
424
|
-
The defect D-2 contract in one place: an
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
Kept separate from the on-disk entry point so the contract is unit-testable
|
|
428
|
-
without touching the filesystem.
|
|
429
|
-
.OUTPUTS
|
|
430
|
-
[hashtable] `@{ ExitCode = <int>; Output = <string> }`.
|
|
247
|
+
The defect D-2 contract in one place: an empty list yields `ExitCode = 0` with
|
|
248
|
+
empty `Output`. No entry of this module produces an empty list any more; the
|
|
249
|
+
shape is kept for callers that assemble their own lists.
|
|
431
250
|
#>
|
|
432
251
|
[CmdletBinding()]
|
|
433
252
|
[OutputType([hashtable])]
|
|
434
|
-
param(
|
|
435
|
-
[Parameter(Mandatory = $true)]
|
|
436
|
-
[AllowEmptyCollection()]
|
|
437
|
-
[string[]]$ValidationError
|
|
438
|
-
)
|
|
253
|
+
param([Parameter(Mandatory = $true)][AllowEmptyCollection()][string[]]$ValidationError)
|
|
439
254
|
|
|
440
|
-
if (@($ValidationError).Count -eq 0) {
|
|
441
|
-
return @{ ExitCode = 0; Output = '' }
|
|
442
|
-
}
|
|
255
|
+
if (@($ValidationError).Count -eq 0) { return @{ ExitCode = 0; Output = '' } }
|
|
443
256
|
return @{ ExitCode = 1; Output = ($ValidationError -join [System.Environment]::NewLine) }
|
|
444
257
|
}
|
|
445
258
|
|
|
446
259
|
function Invoke-DiscoveryArtifactValidation {
|
|
447
260
|
<#
|
|
448
261
|
.SYNOPSIS
|
|
449
|
-
|
|
262
|
+
Compatibility entry of the retired validator: reports the floor, a missing artifact or the validation-required result, never a pass.
|
|
450
263
|
.DESCRIPTION
|
|
451
|
-
|
|
452
|
-
`
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
.OUTPUTS
|
|
456
|
-
[hashtable] `@{ ExitCode = <int>; Output = <string> }`.
|
|
264
|
+
`ValidatorArgs` keeps the CLI shape `@(<artifact-type>, <path>)`. The result
|
|
265
|
+
always carries `ExitCode = 1`: the version floor first, then too few
|
|
266
|
+
arguments, then a missing artifact file (actionable), then the
|
|
267
|
+
validation-required message naming the authoritative service.
|
|
457
268
|
#>
|
|
458
269
|
[CmdletBinding()]
|
|
459
270
|
[OutputType([hashtable])]
|
|
460
271
|
param(
|
|
461
|
-
[Parameter(Mandatory = $true)]
|
|
462
|
-
[
|
|
463
|
-
|
|
464
|
-
[Parameter(Mandatory = $false)]
|
|
465
|
-
[version]$PowerShellVersion = $PSVersionTable.PSVersion
|
|
272
|
+
[Parameter(Mandatory = $true)][AllowEmptyCollection()][string[]]$ValidatorArgs,
|
|
273
|
+
[Parameter(Mandatory = $false)][version]$PowerShellVersion = $PSVersionTable.PSVersion,
|
|
274
|
+
[Parameter(Mandatory = $false)][scriptblock]$TestArtifactPath = { param([string]$Candidate) Test-Path -LiteralPath $Candidate -PathType Leaf }
|
|
466
275
|
)
|
|
467
276
|
|
|
277
|
+
$floor = Get-DiscoveryRuntimeVersionError -PowerShellVersion $PowerShellVersion
|
|
278
|
+
if ($null -ne $floor) { return ConvertTo-DiscoveryValidationResult -ValidationError @($floor) }
|
|
468
279
|
if (@($ValidatorArgs).Count -lt 2) {
|
|
469
|
-
return
|
|
280
|
+
return ConvertTo-DiscoveryValidationResult -ValidationError @('Discovery validation requires an artifact type and a path.')
|
|
470
281
|
}
|
|
471
|
-
|
|
472
282
|
$artifactType = [string]$ValidatorArgs[0]
|
|
473
283
|
$path = [string]$ValidatorArgs[1]
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
return @{ ExitCode = 1; Output = "Artifact not found: $path" }
|
|
284
|
+
if (-not (& $TestArtifactPath $path)) {
|
|
285
|
+
return ConvertTo-DiscoveryValidationResult -ValidationError @("Artifact not found: $path")
|
|
477
286
|
}
|
|
287
|
+
return ConvertTo-DiscoveryValidationResult -ValidationError @((Get-DiscoveryValidationRequiredMessage -ArtifactType $artifactType -Path $path))
|
|
288
|
+
}
|
|
478
289
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
290
|
+
function Get-DiscoveryValidationAuthority {
|
|
291
|
+
<#
|
|
292
|
+
.SYNOPSIS
|
|
293
|
+
Reports the only authority a native hook consults: the protected activation of the workspace on a supported host.
|
|
294
|
+
.DESCRIPTION
|
|
295
|
+
Status is `active`, `missing`, `inactive`, `invalid` or `unsupported-host`;
|
|
296
|
+
Supported is true only for `active`. The message is actionable in every case
|
|
297
|
+
and names the authoritative service. No artifact is read.
|
|
298
|
+
.OUTPUTS
|
|
299
|
+
[pscustomobject] Status, Supported, Message, Service, Directory.
|
|
300
|
+
#>
|
|
301
|
+
[CmdletBinding()]
|
|
302
|
+
[OutputType([pscustomobject])]
|
|
303
|
+
param(
|
|
304
|
+
[Parameter(Mandatory = $true)][string]$WorkspaceRoot,
|
|
305
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$HostEnvironment = $null,
|
|
306
|
+
[Parameter(Mandatory = $false)][AllowNull()][scriptblock]$ReadText = $null
|
|
307
|
+
)
|
|
483
308
|
|
|
484
|
-
|
|
485
|
-
-
|
|
486
|
-
|
|
309
|
+
try {
|
|
310
|
+
if ($null -eq $HostEnvironment) { $HostEnvironment = Get-DiscoveryTrustedHostEnvironment }
|
|
311
|
+
$location = Resolve-DiscoveryAuthorityLocation -WorkspaceRoot $WorkspaceRoot -Platform $HostEnvironment.Platform `
|
|
312
|
+
-UserHome $HostEnvironment.UserHome -LocalAppData $HostEnvironment.LocalAppData -XdgStateHome $HostEnvironment.XdgStateHome
|
|
313
|
+
} catch {
|
|
314
|
+
return [pscustomobject]@{ Status = 'unsupported-host'; Supported = $false; Service = $script:ServiceOperation; Directory = $null; Message = "$($script:ValidationRequiredPrefix) this host cannot resolve the protected discovery authority ($($_.Exception.Message)); discovery agents are fail-closed here and no artifact can be validated locally." }
|
|
315
|
+
}
|
|
316
|
+
$parameters = @{ Location = $location }
|
|
317
|
+
if ($null -ne $ReadText) { $parameters['ReadText'] = $ReadText }
|
|
318
|
+
$activation = Read-DiscoveryActivationState @parameters
|
|
319
|
+
$message = switch ($activation.Status) {
|
|
320
|
+
'active' { "the workspace holds an active protected activation; run $($script:ServiceOperation) through the installed service to validate artifacts and let the native hooks verify the protected receipt." }
|
|
321
|
+
'missing' { "no protected activation exists for this workspace; initialize or configure discovery through the installed service before any artifact gate can pass." }
|
|
322
|
+
'inactive' { 'discovery was deliberately deactivated for this workspace; only a root-owned activation can restore artifact gates.' }
|
|
323
|
+
default { "the protected activation record is unreadable ($($activation.Reason)); the gate fails closed until the service rewrites it." }
|
|
324
|
+
}
|
|
325
|
+
return [pscustomobject]@{
|
|
326
|
+
Status = $activation.Status
|
|
327
|
+
Supported = ($activation.Status -eq 'active')
|
|
328
|
+
Service = $script:ServiceOperation
|
|
329
|
+
Directory = $location.Directory
|
|
330
|
+
Message = "$($script:ValidationRequiredPrefix) $message"
|
|
331
|
+
}
|
|
487
332
|
}
|
|
488
333
|
|
|
489
334
|
Export-ModuleMember -Function @(
|
|
@@ -496,5 +341,7 @@ Export-ModuleMember -Function @(
|
|
|
496
341
|
'Get-DiscoverySchemaArtifactValidationError',
|
|
497
342
|
'Get-DiscoveryArtifactValidationError',
|
|
498
343
|
'ConvertTo-DiscoveryValidationResult',
|
|
499
|
-
'Invoke-DiscoveryArtifactValidation'
|
|
344
|
+
'Invoke-DiscoveryArtifactValidation',
|
|
345
|
+
'Get-DiscoveryValidationRequiredMessage',
|
|
346
|
+
'Get-DiscoveryValidationAuthority'
|
|
500
347
|
)
|