Repositories/EigenverftModule/eigenverft-module-package-definition-1.3.schema.json
|
{
"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://eigenverft.local/schemas/eigenverft-module-package-definition-1.3.schema.json", "title": "Eigenverft module package definition document (wire format 1.3)", "$comment": "META: This file is the JSON Schema for INSTANCE documents (one package definition per file, e.g. MyRuntime.json). It is not itself a package definition. Agents: read x-eigenverftAgentHint next for task disambiguation. Design rationale: artifacts groups targets, releases, and sources so maintainers edit acquisition together; presenceDiscovery vs existingInstallDiscovery separates post-install proof from external/adopted install discovery. Runtime: Eigenverft.Manifested.Sandbox validates instances with PowerShell (DefinitionSchema.Wire1_3.ps1), not this schema file—align both when the wire format changes. Paths: env vars expanded; non-rooted installDirectory templates join package global preferredTargetInstallRootDirectory; slashes normalized. Target constraints.os/cpu match runtime Platform/Architecture (e.g. windows, x64) case-insensitively. Full examples: sibling *.json in this folder; no embedded examples array (too large). PS 5.1 parses this schema as JSON only for repo tests.", "description": "AUTHOR TASK — You are producing or editing ONE complete package-definition JSON object for the Eigenverft.Manifested.Sandbox module. It drives Invoke-PackageDefinitionCommand (Assigned = install/reuse, Removed = uninstall policy). Output must satisfy every required property, additionalProperties:false everywhere enforced, and schemaVersion exactly 1.3.\n\nWHAT TO EMIT: A single JSON file, conventionally named {id}.json (same folder as this schema in the shipped module), containing id, display, dependencies (use [] if none), artifacts, presenceDiscovery, existingInstallDiscovery, and packageOperations. Optional top-level $comment (string) and $schema (URI string pointing at ./eigenverft-module-package-definition-1.3.schema.json) are allowed for editors.\n\nSECTION MEANING: artifacts — which platforms get which files, version catalog, hashes, download sources; presenceDiscovery — files, dirs, commands, registry checks proving the install works (and removal absence where used); existingInstallDiscovery — how to find pre-existing installs (often enabled:false with empty arrays); packageOperations — compatibility policy, how to install (assigned.install oneOf), PATH/shims, how to remove.\n\nSUGGESTED BUILD ORDER: (1) id + display.default; (2) artifacts.targets with constraints.os/cpu per machine or artifact distribution variant; (3) artifacts.releases + targetArtifacts + upstreamRelease as needed; (4) artifacts.sources for download kinds; (5) packageOperations.assigned.install + installDirectory template + pathRegistration consistent with presenceDiscovery paths; (6) presenceDiscovery matching real layout after expand/install; (7) packageOperations.removed mirroring inventory and cleanup.\n\nCOMMON TRAPS: download candidates need sourceId+sourcePath (or artifact sourcePath) OR direct url/urlTemplate; GitHub release sources require real release assets and releaseTag; NSIS and Inno Setup are different install kinds; installer-owned PATH and package-managed shims should be chosen deliberately, not mixed accidentally.\n\nWHEN UNSURE: Clone the shape of an existing sibling definition (e.g. PythonRuntime.json, VSCodeRuntime.json) and only change deltas. If Wire1_3 rejects a document, the runtime assert is authoritative—fix the JSON to match the engine, then update this schema if the wire format truly changed.", "x-eigenverftAgentHint": "If you are an LLM or autonomous coding agent: your likely task is to create or edit a single package-definition INSTANCE JSON file (e.g. MyRuntime.json) that conforms to this schema and to DefinitionSchema.Wire1_3.ps1—not to edit this schema file, VS Code/Cursor settings.json, or package global Config.json unless the user explicitly asks for those. Default intent when the user mentions packages, assign, install, remove, inventory, or shims in this repo: Eigenverft.Manifested.Sandbox Invoke-PackageDefinitionCommand / packageOperations, not editor configuration. Practical workflow: duplicate the closest sibling *.json in this folder, keep id aligned with the filename, bump artifacts.releases as needed, keep presenceDiscovery consistent with assigned.install paths, then sanity-check removed against inventory cleanup. If instructions are ambiguous, prefer a minimal delta to a known-good definition over inventing new object shapes.", "type": "object", "additionalProperties": false, "required": [ "schemaVersion", "id", "display", "artifacts", "presenceDiscovery", "existingInstallDiscovery", "packageOperations" ], "properties": { "$comment": { "type": "string", "description": "Optional free-text note stored inside the INSTANCE package definition JSON; safe for human changelog-style remarks. Runtime ignores it." }, "$schema": { "type": "string", "description": "Optional. In instance documents set to ./eigenverft-module-package-definition-1.3.schema.json (same folder) so editors attach validation; runtime ignores." }, "schemaVersion": { "type": "string", "const": "1.3", "description": "Must be the literal string 1.3. This is the only supported package-definition wire version for new documents." }, "id": { "$ref": "#/$defs/identifier", "description": "Primary key for this package: must match the filename stem (ExamplePackage.json → id ExamplePackage). Used in Invoke-PackageDefinitionCommand -DefinitionId, install slot ids, and inventory." }, "display": { "$ref": "#/$defs/display", "description": "Human-readable names and summaries for logs and UI; does not affect install mechanics." }, "dependencies": { "type": "array", "description": "Other package definitions that must reach Assigned (successfully) before this definition is assigned. Each entry references repositoryId (defaults to the parent definition repository when omitted) and definitionId. Removal does not automatically uninstall dependencies unless a future policy implements that.", "items": { "$ref": "#/$defs/dependency" } }, "artifacts": { "$ref": "#/$defs/artifacts", "description": "Acquisition and selection: declare targets (per OS/CPU), releases with versions and hashes, artifact file names, and download sources. This block answers what to download and which release applies to which machine." }, "presenceDiscovery": { "$ref": "#/$defs/presenceDiscovery", "description": "Post-install proof: files, directories, commands, and optional registry/metadata checks under the resolved install directory. Must align with assigned.install layout or readiness and removal checks will fail." }, "existingInstallDiscovery": { "$ref": "#/$defs/existingInstallDiscovery", "description": "How to detect installs that were not created by this package inventory (adoption). Use enabled:false and empty searchLocations/installRootRules when this package never adopts external trees." }, "packageOperations": { "$ref": "#/$defs/packageOperations", "description": "Desired-state machine: compatibility policy, assigned (how to install and register PATH/shims), removed (policy, delete operation, cleanup). This block answers how the engine mutates the machine." } }, "$defs": { "identifier": { "type": "string", "minLength": 1, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*$", "description": "Portable id segment. Keep ids stable and avoid spaces so paths, inventory keys, and repository references stay predictable." }, "display": { "type": "object", "additionalProperties": false, "required": [ "default" ], "properties": { "default": { "$ref": "#/$defs/displayEntry" } } }, "displayEntry": { "type": "object", "additionalProperties": false, "required": [ "name", "publisher", "corporation", "summary" ], "properties": { "name": { "type": "string", "minLength": 1 }, "publisher": { "type": "string", "minLength": 1 }, "corporation": { "type": "string", "minLength": 1 }, "summary": { "type": "string", "minLength": 1 } } }, "dependency": { "type": "object", "additionalProperties": false, "required": [ "repositoryId", "definitionId" ], "properties": { "repositoryId": { "$ref": "#/$defs/identifier", "description": "Package-definition repository id, not a vendor source id." }, "definitionId": { "$ref": "#/$defs/identifier", "description": "Package definition id to assign before this package." } } }, "artifacts": { "type": "object", "$comment": "AUTHOR FOCUS: Define everything needed to select and download the right binary for each machine class. targets[] = one row per selectable lane (releaseTrack + artifactDistributionVariant + constraints). releases[] = version rows with targetArtifacts keyed by target id and optional upstreamRelease. sources = named download roots used by acquisitionCandidates. Generators: add a target per OS/CPU you support, then a release row per shipped version with matching hashes.", "additionalProperties": false, "required": [ "targets", "releases", "sources" ], "properties": { "$comment": { "type": "string" }, "targets": { "type": "array", "minItems": 1, "description": "Selectable artifact target lanes such as stable windows_amd64 or stable q8-0.", "items": { "$ref": "#/$defs/artifactTarget" } }, "releases": { "type": "array", "minItems": 1, "description": "Concrete release/version facts and per-target artifact trust metadata.", "items": { "$ref": "#/$defs/artifactRelease" } }, "sources": { "type": "object", "description": "Definition-local artifact sources referenced by acquisition candidates and upstreamRelease.", "additionalProperties": { "$ref": "#/$defs/artifactSourceEndpoint" } } } }, "artifactTarget": { "type": "object", "$comment": "artifactDistributionVariant is intentionally long because it is not only platform. It can represent platform packaging, CPU/GPU build, model quantization, installer edition, or another distributed artifact form.", "additionalProperties": false, "required": [ "id", "releaseTrack", "artifactDistributionVariant", "constraints", "versionSelection" ], "properties": { "$comment": { "type": "string" }, "id": { "$ref": "#/$defs/identifier", "description": "Artifact target id used as key in artifacts.releases[].targetArtifacts." }, "releaseTrack": { "type": "string", "minLength": 1, "description": "Update lane such as stable." }, "artifactDistributionVariant": { "type": "string", "minLength": 1, "description": "The distributed artifact form for this target, for example windows_amd64, win32-x64, q8-0, or cpu-x64." }, "constraints": { "$ref": "#/$defs/constraints", "description": "Machine constraints used to decide whether this target is selectable." }, "versionSelection": { "$ref": "#/$defs/versionSelection", "description": "How the runtime selects a release from artifacts.releases for this target." }, "fileNameTemplate": { "type": "string", "minLength": 1, "description": "Default package file or asset name template for this target. Omit for operations such as npmGlobalPackage that do not acquire a raw package file." }, "acquisitionCandidates": { "$ref": "#/$defs/acquisitionCandidates", "description": "Default ordered candidates used to acquire the raw artifact for this target. Omit when assignment does not need a package file." } } }, "constraints": { "type": "object", "additionalProperties": false, "$comment": "Matched against the resolved runtime context for the machine running the package engine (not expressed as a closed enum in JSON Schema). Use the same tokens the engine emits: os is compared to Platform (e.g. windows, linux, macos); cpu is compared to Architecture (e.g. x64, arm64, x86). Matching is case-insensitive. Each array must list at least one token; the engine accepts the target if the actual value equals any listed entry.", "required": [ "os", "cpu" ], "properties": { "os": { "type": "array", "minItems": 1, "description": "Allowed platform tokens for this artifact target. Compared case-insensitively to the engine Platform value (see runtime context).", "items": { "type": "string", "minLength": 1 } }, "cpu": { "type": "array", "minItems": 1, "description": "Allowed CPU architecture tokens for this artifact target. Compared case-insensitively to the engine Architecture value.", "items": { "type": "string", "minLength": 1 } } } }, "versionSelection": { "type": "object", "$comment": "latestByVersion selects from this definition's artifacts.releases. It is not a network latest lookup.", "additionalProperties": false, "required": [ "strategy", "allowPrerelease" ], "properties": { "strategy": { "type": "string", "enum": [ "latestByVersion" ] }, "allowPrerelease": { "type": "boolean" } } }, "artifactRelease": { "type": "object", "$comment": "This is the fast update surface for maintainers: add a release with version, release tracks, upstream release tag, and per-target hashes.", "additionalProperties": false, "required": [ "version", "releaseTracks", "targetArtifacts" ], "properties": { "$comment": { "type": "string" }, "version": { "type": "string", "minLength": 1, "description": "Package version used for selection, paths, validation tokens, and inventory." }, "releaseTracks": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } }, "upstreamRelease": { "$ref": "#/$defs/upstreamRelease", "description": "Optional upstream release metadata shared by target artifacts in this release." }, "targetArtifacts": { "type": "object", "minProperties": 1, "description": "Concrete artifact facts keyed by artifacts.targets[].id.", "additionalProperties": { "$ref": "#/$defs/targetArtifact" } } } }, "upstreamRelease": { "type": "object", "additionalProperties": false, "$comment": "Conditional requirements: when sourceId resolves to a source whose kind requires a fixed upstream tag (for example githubRelease), the runtime expects releaseTag to be populated. JSON Schema cannot express that dependency here; validate combinations against Wire1_3 or follow existing definitions.", "required": [ "sourceId" ], "properties": { "sourceId": { "$ref": "#/$defs/identifier", "description": "Key into artifacts.sources for shared upstream metadata on this release row." }, "releaseTag": { "type": "string", "minLength": 1, "description": "Upstream release tag or version label used when resolving downloads from the referenced source (required in practice when that source kind needs a tag; see artifacts.sources[].kind in the same document)." } } }, "targetArtifact": { "type": "object", "additionalProperties": false, "required": [ "artifactId" ], "properties": { "artifactId": { "type": "string", "minLength": 1, "description": "Stable selected-artifact id written into results and inventory." }, "fileName": { "type": "string", "minLength": 1, "description": "Exact package file or asset name override for this release/target." }, "sourcePath": { "type": "string", "description": "Optional source-relative path override for this release/target." }, "acquisitionCandidates": { "$ref": "#/$defs/acquisitionCandidates", "description": "Optional acquisition candidate override for this release/target." }, "url": { "type": "string", "description": "Optional direct artifact URL template. Prefer candidate.urlTemplate for per-source policy; use this only when the artifact itself owns the full URL." }, "urlTemplate": { "type": "string", "description": "Optional direct artifact URL template using tokens such as {version}, {releaseTag}, {releaseTrack}, and {artifactDistributionVariant}." }, "contentHash": { "$ref": "#/$defs/contentHash", "description": "Trust boundary for fixed package files." }, "publisherSignature": { "$ref": "#/$defs/publisherSignature", "description": "Publisher signature requirement for executable artifacts when fixed hashes are unsuitable." } } }, "acquisitionCandidates": { "type": "array", "minItems": 1, "description": "Ordered candidates used to acquire raw package files. Lower searchOrder runs first.", "items": { "$ref": "#/$defs/acquisitionCandidate" } }, "acquisitionCandidate": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "kind", "searchOrder", "verification" ], "properties": { "kind": { "const": "packageDepot" }, "searchOrder": { "type": "integer", "minimum": 0 }, "verification": { "$ref": "#/$defs/verification" } } }, { "type": "object", "additionalProperties": false, "required": [ "kind", "searchOrder", "verification" ], "properties": { "kind": { "const": "download" }, "sourceId": { "$ref": "#/$defs/identifier", "description": "Required when resolving through artifacts.sources + sourcePath. Omit for direct url/urlTemplate downloads." }, "sourcePath": { "type": "string", "description": "Source-relative path appended to artifacts.sources[sourceId].baseUri. May also be supplied by targetArtifacts[].sourcePath." }, "url": { "type": "string", "description": "Direct absolute download URL. Mutually exclusive with sourceId/sourcePath." }, "urlTemplate": { "type": "string", "description": "Direct absolute download URL template with {version}, {releaseTag}, {releaseTrack}, and {artifactDistributionVariant}. Mutually exclusive with sourceId/sourcePath." }, "searchOrder": { "type": "integer", "minimum": 0 }, "verification": { "$ref": "#/$defs/verification" } } }, { "type": "object", "additionalProperties": false, "required": [ "kind", "sourcePath", "searchOrder", "verification" ], "properties": { "kind": { "const": "filesystem" }, "sourceId": { "$ref": "#/$defs/identifier" }, "sourcePath": { "type": "string" }, "searchOrder": { "type": "integer", "minimum": 0 }, "verification": { "$ref": "#/$defs/verification" } } } ] }, "verification": { "type": "object", "additionalProperties": false, "required": [ "mode" ], "properties": { "mode": { "type": "string", "enum": [ "required", "optional", "none" ] } } }, "artifactSourceEndpoint": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "kind", "baseUri" ], "properties": { "kind": { "const": "download" }, "baseUri": { "type": "string", "minLength": 1 } } }, { "type": "object", "$comment": "GitHub field names are prefixed with github to avoid confusion with package repository ids.", "additionalProperties": false, "required": [ "kind", "githubOwner", "githubRepository" ], "properties": { "kind": { "const": "githubRelease" }, "githubOwner": { "type": "string", "minLength": 1 }, "githubRepository": { "type": "string", "minLength": 1 } } } ] }, "presenceDiscovery": { "type": "object", "$comment": "Presence discovery replaces providedTools/discovery wording. It describes what proves presence, not where to fetch or how to install. Relative paths under files, directories, commands, apps, metadataFiles, signatures, fileDetails, and registry are resolved from the effective assigned install directory root after the package is placed on disk (the same root used for readiness and removal verification unless a step overrides it).", "additionalProperties": false, "required": [ "files", "directories", "commands", "apps", "metadataFiles", "signatures", "fileDetails", "registry" ], "properties": { "$comment": { "type": "string" }, "files": { "type": "array", "description": "Relative file paths that must exist under the install root (slash-separated segments are fine; the engine normalizes).", "items": { "type": "string" } }, "directories": { "type": "array", "description": "Relative directory paths that must exist under the install root.", "items": { "type": "string" } }, "commands": { "type": "array", "items": { "$ref": "#/$defs/presenceCommand" } }, "apps": { "type": "array", "items": { "$ref": "#/$defs/presenceApp" } }, "metadataFiles": { "type": "array", "items": { "$ref": "#/$defs/metadataFileProbe" } }, "signatures": { "type": "array", "items": { "$ref": "#/$defs/signatureProbe" } }, "fileDetails": { "type": "array", "items": { "$ref": "#/$defs/fileDetailsProbe" } }, "registry": { "type": "array", "items": { "$ref": "#/$defs/registryProbe" } } } }, "presenceCommand": { "type": "object", "additionalProperties": false, "required": [ "name", "relativePath", "requiredForState", "exposeCommand" ], "properties": { "name": { "type": "string", "minLength": 1 }, "relativePath": { "type": "string", "minLength": 1, "description": "Executable path relative to the install root (for example python.exe or bin/code.cmd)." }, "requiredForState": { "type": "boolean" }, "exposeCommand": { "type": "boolean" }, "stateChecks": { "type": "array", "description": "Optional command invocations used to validate runtime behavior. When any property is set, the runtime uses the check; leaving every property out means the check is skipped for that entry.", "items": { "$ref": "#/$defs/commandStateCheck" } } } }, "presenceApp": { "type": "object", "additionalProperties": false, "required": [ "name", "relativePath", "requiredForState", "exposeApp" ], "properties": { "name": { "type": "string", "minLength": 1 }, "relativePath": { "type": "string", "minLength": 1 }, "requiredForState": { "type": "boolean" }, "exposeApp": { "type": "boolean" } } }, "commandStateCheck": { "type": "object", "additionalProperties": false, "$comment": "Optional subprocess check: when used, the engine runs the discovered command with optional arguments, matches stdout/stderr against outputPattern when provided, and may compare captured text to expectedValue. All properties are optional at the schema level; practical checks usually supply at least arguments or outputPattern—mirror a working definition if unsure.", "properties": { "arguments": { "type": "array", "items": { "type": "string" } }, "outputPattern": { "type": "string" }, "expectedValue": { "type": "string" } } }, "metadataFileProbe": { "type": "object", "additionalProperties": true, "$comment": "additionalProperties allows forward-compatible metadata keys beyond relativePath; only keys understood by the engine have effect—treat unknown keys as documentation until Wire1_3 recognizes them.", "required": [ "relativePath" ], "properties": { "relativePath": { "type": "string" } } }, "signatureProbe": { "type": "object", "additionalProperties": false, "required": [ "relativePath", "requireValid", "subjectContains" ], "properties": { "relativePath": { "type": "string" }, "requireValid": { "type": "boolean" }, "subjectContains": { "type": "string" } } }, "fileDetailsProbe": { "type": "object", "additionalProperties": true, "$comment": "Same forward-compat pattern as metadataFileProbe: relativePath is required; other properties enable structured Win32 version resource checks when supported.", "required": [ "relativePath" ], "properties": { "relativePath": { "type": "string" }, "fileVersion": { "type": "string" }, "productVersion": { "type": "string" }, "productName": { "type": "string" }, "fileDescription": { "type": "string" } } }, "registryProbe": { "type": "object", "additionalProperties": false, "description": "Probes Windows registry values under one or more key paths. When expectedValue is omitted, the probe only requires the value to exist.", "required": [ "paths", "valueName" ], "properties": { "paths": { "type": "array", "minItems": 1, "items": { "type": "string" }, "description": "Registry key paths to inspect (first successful read wins)." }, "valueName": { "type": "string" }, "operator": { "type": "string", "description": "String comparison operator when expectedValue is set. Supported: =, == (case-insensitive equality), !=, and version compares >, >=, <, <= after parsing both sides as version text." }, "expectedValue": { "type": "string", "description": "Optional template-expanded expected content; omit to require only that the value exists." } } }, "existingInstallDiscovery": { "type": "object", "$comment": "Existing install discovery is shared by assignment/adoption and removal. Give search locations stable ids so removal operations can reference the same registry/path discovery data.", "additionalProperties": false, "required": [ "enabled", "searchLocations", "installRootRules" ], "properties": { "$comment": { "type": "string" }, "enabled": { "type": "boolean", "description": "When false, discovery is disabled and searchLocations/installRootRules are ignored at runtime; the schema still requires those arrays to be present (use empty arrays)." }, "searchLocations": { "type": "array", "items": { "$ref": "#/$defs/existingInstallSearchLocation" } }, "installRootRules": { "type": "array", "items": { "$ref": "#/$defs/installRootRule" } } } }, "existingInstallSearchLocation": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "id", "kind", "searchOrder", "name" ], "properties": { "id": { "$ref": "#/$defs/identifier" }, "kind": { "const": "command" }, "searchOrder": { "type": "integer", "minimum": 0 }, "name": { "type": "string", "minLength": 1, "description": "Executable command name resolved as an application from PATH." } } }, { "type": "object", "additionalProperties": false, "required": [ "id", "kind", "searchOrder", "path" ], "properties": { "id": { "$ref": "#/$defs/identifier" }, "kind": { "const": "path" }, "searchOrder": { "type": "integer", "minimum": 0 }, "path": { "type": "string", "minLength": 1, "description": "Concrete file path to probe." } } }, { "type": "object", "additionalProperties": false, "required": [ "id", "kind", "searchOrder", "path" ], "properties": { "id": { "$ref": "#/$defs/identifier" }, "kind": { "const": "directory" }, "searchOrder": { "type": "integer", "minimum": 0 }, "path": { "type": "string", "minLength": 1, "description": "Concrete install directory path to probe." } } }, { "type": "object", "additionalProperties": false, "required": [ "id", "kind", "searchOrder", "paths", "installDirectorySource" ], "properties": { "id": { "$ref": "#/$defs/identifier", "description": "Stable id so removal can reference this uninstall-registry source." }, "kind": { "const": "windowsUninstallRegistryKey" }, "searchOrder": { "type": "integer", "minimum": 0 }, "paths": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "Direct registry key paths such as HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Example." }, "installDirectorySource": { "type": "string", "enum": [ "installLocation", "displayIcon", "displayIconDirectory", "uninstallString", "uninstallStringDirectory" ] } } } ], "description": "Existing install search location. Use command/path/directory for portable tools, windowsUninstallRegistryKey for installer-owned applications." }, "installRootRule": { "type": "object", "additionalProperties": false, "$comment": "Maps a discovered candidate file path to an install root. Today the engine implements match.kind=fileName with match.value equal to the leaf file name (case-insensitive); other match shapes are reserved. installRootRelativePath is joined relative to the directory containing the matched file (use . for the parent directory itself).", "required": [ "match", "installRootRelativePath" ], "properties": { "match": { "type": "object", "additionalProperties": false, "required": [ "kind", "value" ], "properties": { "kind": { "const": "fileName" }, "value": { "type": "string", "minLength": 1 } }, "description": "Supported shape in Wire1_3: { \"kind\": \"fileName\", \"value\": \"example.exe\" }." }, "installRootRelativePath": { "type": "string", "description": "Relative path from the discovered file's directory to the install root." } } }, "packageOperations": { "type": "object", "$comment": "AUTHOR FOCUS: assigned chooses install engine (expandArchive, npmGlobalPackage, nsisInstaller, innoSetupInstaller, runInstaller, placePackageFile) and must agree with presenceDiscovery paths. removed must undo ownership safely (inventory row, shims, delete directory). policy sets compatibility and ownership rules before install.", "additionalProperties": false, "required": [ "policy", "assigned", "removed" ], "properties": { "$comment": { "type": "string" }, "policy": { "$ref": "#/$defs/packageOperationPolicy" }, "assigned": { "$ref": "#/$defs/assignedOperation" }, "removed": { "$ref": "#/$defs/removedOperation" } } }, "packageOperationPolicy": { "type": "object", "additionalProperties": false, "required": [ "ownershipPolicy", "compatibility" ], "properties": { "ownershipPolicy": { "$ref": "#/$defs/ownershipPolicy" }, "compatibility": { "$ref": "#/$defs/compatibility" } } }, "assignedOperation": { "type": "object", "$comment": "Assigned receives a selected artifact and makes the package ready. Artifact lookup stays under artifacts.", "additionalProperties": false, "required": [ "install", "readyStateCheck", "pathRegistration", "versionUpdatePolicy" ], "properties": { "$comment": { "type": "string" }, "install": { "$ref": "#/$defs/assignInstallOperation" }, "readyStateCheck": { "$ref": "#/$defs/readyStateCheck" }, "pathRegistration": { "$ref": "#/$defs/pathRegistration" }, "versionUpdatePolicy": { "$ref": "#/$defs/versionUpdatePolicy" } } }, "assignInstallOperation": { "oneOf": [ { "$ref": "#/$defs/assignExpandArchive" }, { "$ref": "#/$defs/assignNpmGlobalPackage" }, { "$ref": "#/$defs/assignPlacePackageFile" }, { "$ref": "#/$defs/assignNsisInstaller" }, { "$ref": "#/$defs/assignInnoSetupInstaller" }, { "$ref": "#/$defs/assignRunInstaller" } ] }, "assignExpandArchive": { "type": "object", "additionalProperties": false, "$comment": "installDirectory follows the same root rules as other assigned operations: expand environment variables, normalize slashes, and if not absolute, prefix with preferredTargetInstallRootDirectory. expandedRoot names the directory inside the archive that becomes the logical payload root after extraction.", "required": [ "kind", "installDirectory", "expandedRoot", "createDirectories" ], "properties": { "kind": { "const": "expandArchive" }, "installDirectory": { "type": "string", "description": "Target install directory template (supports tokens such as {definitionId}, {releaseTrack}, {version}, {artifactDistributionVariant})." }, "expandedRoot": { "type": "string", "description": "Path inside the expanded archive that anchors relative discovery paths (often a single folder like tools)." }, "createDirectories": { "type": "array", "items": { "type": "string" } } } }, "assignNpmGlobalPackage": { "type": "object", "additionalProperties": false, "required": [ "kind", "installerCommand", "packageSpec", "installDirectory" ], "properties": { "kind": { "const": "npmGlobalPackage" }, "installerCommand": { "type": "string" }, "packageSpec": { "type": "string" }, "installDirectory": { "type": "string", "description": "Target directory template for the npm global package layout (same path rules as expandArchive.installDirectory)." } } }, "assignPlacePackageFile": { "type": "object", "additionalProperties": false, "required": [ "kind", "installDirectory", "targetRelativePath" ], "properties": { "kind": { "const": "placePackageFile" }, "installDirectory": { "type": "string", "description": "Destination directory template for the copied artifact (same path rules as expandArchive.installDirectory)." }, "targetRelativePath": { "type": "string", "description": "Relative path within the install directory where the package file is written." } } }, "assignNsisInstaller": { "type": "object", "additionalProperties": false, "$comment": "NSIS-only installer adapter. NSIS requires the target directory argument last and unquoted, usually /D=<installDirectory>. Do not use this for Inno Setup; use innoSetupInstaller.", "required": [ "kind", "installDirectory", "commandArguments", "targetDirectoryArgument" ], "properties": { "kind": { "const": "nsisInstaller" }, "installDirectory": { "type": "string" }, "installerKind": { "const": "nsis" }, "uiMode": { "type": "string" }, "elevation": { "$ref": "#/$defs/elevationMode" }, "timeoutSec": { "type": "integer", "minimum": 1 }, "commandArguments": { "type": "array", "items": { "type": "string" } }, "targetDirectoryArgument": { "type": "object", "additionalProperties": false, "required": [ "enabled", "prefix" ], "properties": { "enabled": { "type": "boolean" }, "prefix": { "type": "string", "minLength": 1, "description": "Usually /D=. The engine appends the install directory unquoted and last." } }, "description": "NSIS target directory argument. If enabled, the engine appends {prefix}{installDirectory} as the final argument without quotes." }, "successExitCodes": { "$ref": "#/$defs/exitCodes" }, "restartExitCodes": { "$ref": "#/$defs/exitCodes" } } }, "assignInnoSetupInstaller": { "type": "object", "additionalProperties": false, "$comment": "Inno Setup installer adapter. Common silent args are /VERYSILENT /NORESTART /SUPPRESSMSGBOXES and optional /MERGETASKS=... . Target directory is passed as /DIR=\"<installDirectory>\" when targetDirectoryArgument.enabled=true.", "required": [ "kind", "installDirectory", "commandArguments", "targetDirectoryArgument" ], "properties": { "kind": { "const": "innoSetupInstaller" }, "installDirectory": { "type": "string" }, "uiMode": { "type": "string" }, "elevation": { "$ref": "#/$defs/elevationMode" }, "timeoutSec": { "type": "integer", "minimum": 1 }, "commandArguments": { "type": "array", "items": { "type": "string" } }, "targetDirectoryArgument": { "type": "object", "additionalProperties": false, "required": [ "enabled", "prefix", "quoteValue" ], "properties": { "enabled": { "type": "boolean" }, "prefix": { "type": "string", "minLength": 1, "description": "Usually /DIR=." }, "quoteValue": { "type": "boolean", "description": "Usually true for Inno Setup because install paths commonly contain spaces." } } }, "successExitCodes": { "$ref": "#/$defs/exitCodes" }, "restartExitCodes": { "$ref": "#/$defs/exitCodes" } } }, "assignRunInstaller": { "type": "object", "additionalProperties": false, "required": [ "kind", "targetKind", "installerKind", "uiMode", "elevation", "timeoutSec", "commandArguments", "successExitCodes", "restartExitCodes" ], "properties": { "kind": { "const": "runInstaller" }, "targetKind": { "type": "string", "enum": [ "directory", "machinePrerequisite" ] }, "installerKind": { "type": "string" }, "uiMode": { "type": "string" }, "elevation": { "$ref": "#/$defs/elevationMode" }, "timeoutSec": { "type": "integer", "minimum": 1 }, "logRelativePath": { "type": "string" }, "commandArguments": { "type": "array", "items": { "type": "string" } }, "successExitCodes": { "$ref": "#/$defs/exitCodes" }, "restartExitCodes": { "$ref": "#/$defs/exitCodes" } } }, "readyStateCheck": { "type": "object", "additionalProperties": false, "required": [ "use", "expectedVersion", "require" ], "properties": { "use": { "const": "presenceDiscovery" }, "expectedVersion": { "type": "string" }, "require": { "$ref": "#/$defs/presenceRequirementFlags" } } }, "versionUpdatePolicy": { "type": "object", "additionalProperties": false, "required": [ "whenAssigned", "onSameSelectedVersion", "onNewSelectedVersion" ], "properties": { "whenAssigned": { "const": "trackSelectedVersion" }, "onSameSelectedVersion": { "const": "reuseOrRepair" }, "onNewSelectedVersion": { "type": "string", "enum": [ "replacePackageOwnedInstall", "fail" ] } } }, "removedOperation": { "type": "object", "$comment": "Removal references presenceDiscovery/existingInstallDiscovery instead of duplicating discovery facts. Policy decides what ownership classes may be touched.", "additionalProperties": false, "required": [ "policy", "operation", "absenceVerification", "postRemoveCleanup" ], "properties": { "$comment": { "type": "string" }, "policy": { "$ref": "#/$defs/removePolicy" }, "operation": { "$ref": "#/$defs/removeOperation" }, "absenceVerification": { "$ref": "#/$defs/absenceVerification" }, "postRemoveCleanup": { "$ref": "#/$defs/postRemoveCleanup" } } }, "removePolicy": { "type": "object", "additionalProperties": false, "required": [ "whenNotInInventory", "allowedInventoryOwnershipKinds", "allowUntrackedExternalRemoval", "removeDependencies" ], "properties": { "whenNotInInventory": { "type": "string", "enum": [ "succeed", "fail" ] }, "allowedInventoryOwnershipKinds": { "type": "array", "items": { "type": "string", "enum": [ "PackageInstalled", "PackageApplied", "AdoptedExternal" ] } }, "allowUntrackedExternalRemoval": { "type": "boolean", "description": "High-risk opt-in. When false, removal never deletes an external install discovered live without inventory." }, "removeDependencies": { "type": "boolean", "description": "Whether removing this package should also remove dependencies. Expected false for v1." } } }, "removeOperation": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "kind", "pathSource" ], "properties": { "kind": { "const": "deleteInstallDirectory" }, "pathSource": { "const": "inventory.installDirectory", "description": "Delete the install directory tracked in inventory, not a newly computed directory from current config." } } }, { "type": "object", "additionalProperties": false, "required": [ "kind", "commandSource", "commandArguments", "elevation", "timeoutSec", "successExitCodes", "restartExitCodes", "uiMode" ], "properties": { "kind": { "type": "string", "enum": [ "nsisUninstaller", "innoSetupUninstaller" ] }, "commandSource": { "$ref": "#/$defs/uninstallCommandSource" }, "commandArguments": { "type": "array", "items": { "type": "string" } }, "elevation": { "$ref": "#/$defs/elevationMode" }, "timeoutSec": { "type": "integer", "minimum": 1 }, "successExitCodes": { "$ref": "#/$defs/exitCodes" }, "restartExitCodes": { "$ref": "#/$defs/exitCodes" }, "uiMode": { "type": "string" } } }, { "type": "object", "additionalProperties": false, "required": [ "kind" ], "properties": { "kind": { "const": "none" } } } ] }, "uninstallCommandSource": { "type": "object", "additionalProperties": false, "required": [ "use", "searchLocationId", "registryValueOrder" ], "properties": { "use": { "const": "existingInstallDiscovery" }, "searchLocationId": { "$ref": "#/$defs/identifier", "description": "Id of an existingInstallDiscovery.searchLocations entry." }, "registryValueOrder": { "type": "array", "minItems": 1, "items": { "type": "string", "enum": [ "QuietUninstallString", "UninstallString" ] } } } }, "absenceVerification": { "type": "object", "additionalProperties": false, "required": [ "use", "require" ], "properties": { "use": { "const": "presenceDiscovery" }, "require": { "$ref": "#/$defs/presenceRequirementFlags" } } }, "postRemoveCleanup": { "type": "object", "additionalProperties": false, "required": [ "packageInventoryRecord", "generatedShims", "pathEntries", "workDirectories" ], "properties": { "packageInventoryRecord": { "type": "boolean" }, "generatedShims": { "type": "boolean" }, "pathEntries": { "type": "boolean" }, "workDirectories": { "type": "boolean" } } }, "presenceRequirementFlags": { "type": "object", "additionalProperties": false, "required": [ "files", "directories", "commands", "apps", "metadataFiles", "signatures", "fileDetails", "registry" ], "properties": { "files": { "type": "boolean" }, "directories": { "type": "boolean" }, "commands": { "type": "boolean" }, "apps": { "type": "boolean" }, "metadataFiles": { "type": "boolean" }, "signatures": { "type": "boolean" }, "fileDetails": { "type": "boolean" }, "registry": { "type": "boolean" } } }, "pathRegistration": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "mode" ], "properties": { "mode": { "const": "none" } } }, { "type": "object", "additionalProperties": false, "required": [ "mode", "source" ], "properties": { "mode": { "type": "string", "enum": [ "user", "machine" ] }, "source": { "$ref": "#/$defs/pathRegistrationSource" } } } ] }, "pathRegistrationSource": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "kind", "use" ], "properties": { "kind": { "const": "shim" }, "use": { "const": "presenceDiscovery.commands" } } }, { "type": "object", "additionalProperties": false, "required": [ "kind", "value" ], "properties": { "kind": { "type": "string", "enum": [ "commandEntryPoint", "appEntryPoint", "installRelativeDirectory" ] }, "value": { "type": "string", "minLength": 1 } } } ] }, "ownershipPolicy": { "type": "object", "additionalProperties": false, "required": [ "allowAdoptExternal", "upgradeAdoptedInstall", "requirePackageOwnership" ], "properties": { "allowAdoptExternal": { "type": "boolean" }, "upgradeAdoptedInstall": { "type": "boolean" }, "requirePackageOwnership": { "type": "boolean" } } }, "compatibility": { "type": "object", "additionalProperties": false, "required": [ "checks" ], "properties": { "checks": { "type": "array", "items": { "$ref": "#/$defs/compatibilityCheck" } } } }, "compatibilityCheck": { "oneOf": [ { "type": "object", "additionalProperties": false, "required": [ "kind", "operator", "value" ], "properties": { "kind": { "const": "osVersion" }, "operator": { "type": "string", "description": "Version comparison operator for the host OS version string. Supported: =, ==, !=, >, >=, <, <= (same rules as package selection compatibility)." }, "value": { "type": "string", "description": "Expected OS version text compared against Environment.OSVersion." }, "onFail": { "$ref": "#/$defs/onFail", "description": "When omitted, failed checks default to fail behavior in the engine." } } }, { "type": "object", "additionalProperties": false, "required": [ "kind", "operator", "value" ], "properties": { "kind": { "type": "string", "enum": [ "physicalMemoryGiB", "videoMemoryGiB", "physicalOrVideoMemoryGiB" ] }, "operator": { "type": "string", "description": "Numeric comparison operator for GiB thresholds. Supported: =, ==, !=, >, >=, <, <=." }, "value": { "type": "number", "description": "Threshold in gibibytes (GiB), compared against detected memory for the machine." }, "onFail": { "$ref": "#/$defs/onFail", "description": "When omitted, failed checks default to fail behavior in the engine." } } } ], "$comment": "This oneOf currently covers osVersion and memory GiB checks implemented in Wire1_3; additional compatibility kinds may appear in definitions before this schema lists them—extend the schema when adding new kinds." }, "onFail": { "type": "string", "description": "Compatibility check handling when a check fails. When omitted on a check object, the engine defaults to fail.", "enum": [ "fail", "warn" ] }, "contentHash": { "type": "object", "additionalProperties": false, "required": [ "algorithm", "value" ], "properties": { "algorithm": { "const": "sha256" }, "value": { "type": "string", "minLength": 1 } } }, "publisherSignature": { "type": "object", "additionalProperties": false, "required": [ "kind", "requireValid", "subjectContains" ], "properties": { "kind": { "const": "authenticode" }, "requireValid": { "type": "boolean" }, "subjectContains": { "type": "string", "minLength": 1 } } }, "elevationMode": { "type": "string", "enum": [ "none", "required", "auto" ] }, "exitCodes": { "type": "array", "items": { "type": "integer" } } } } |