Isystem.PowerShell.PowerPlatform.Dataverse.psd1

#
# Module manifest for module 'Isystem.PowerShell.PowerPlatform.Dataverse'
#
# Generated by: Ondrej Kracmar
#
# Generated on: 09/21/2026
#

@{

# Script module or binary module file associated with this manifest.
RootModule = 'Isystem.PowerShell.PowerPlatform.Dataverse.psm1'

# Version number of this module.
ModuleVersion = '1.0.0'

# Supported PSEditions
CompatiblePSEditions = 'Core'

# ID used to uniquely identify this module
GUID = '4f78bc29-fd8d-444c-a449-a244eeb23a79'

# Author of this module
Author = 'Ondrej Kracmar'

# Company or vendor of this module
CompanyName = 'Isystem'

# Copyright statement for this module
Copyright = '(c) Isystem. All rights reserved.'

# Description of the functionality provided by this module
Description = 'Session-based cmdlets for Microsoft Dataverse (Power Platform, Dynamics 365): CRUD, upsert by alternate key, batches, transactions, FetchXML and paging. Authenticates with connection string, client secret, certificate, managed identity, Isystem.AzAuth modes, or a delegated user sign-in whose token cache the caller stores (Key Vault) for environments without application users.'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '7.5'

# Name of the PowerShell host required by this module
# PowerShellHostName = ''

# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''

# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = 'Isystem.PowerShell.PowerPlatform.Dataverse.Format.ps1xml'

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @()

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = 'Connect-PSDataverse', 'Disconnect-PSDataverse', 
               'Get-PSDataverseConnection', 'Get-PSDataverseRecord', 
               'Get-PSDataverseRecordCount', 'Find-PSDataverseRecord', 
               'Test-PSDataverseRecord', 'New-PSDataverseRecord', 
               'Set-PSDataverseRecord', 'Remove-PSDataverseRecord', 
               'Invoke-PSDataverseBatch', 'Invoke-PSDataverseTransaction', 
               'Invoke-PSDataverseFetchXml', 'Get-PSDataverseTokenCache'

# Variables to export from this module
# VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()

# DSC resources to export from this module
# DscResourcesToExport = @()

# List of all modules packaged with this module
# ModuleList = @()

# List of all files packaged with this module
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{

    PSData = @{

        # Tags applied to this module. These help with module discovery in online galleries.
        Tags = 'Dataverse','PowerPlatform','Dynamics365','CRM','PowerApps','Upsert','PSEdition_Core','Windows','Linux','MacOS'

        # A URL to the license for this module.
        LicenseUri = 'https://github.com/ondrejkracmar/Isystem.PowerShell.PowerPlatform.Dataverse/blob/main/LICENSE'

        # A URL to the main website for this project.
        ProjectUri = 'https://github.com/ondrejkracmar/Isystem.PowerShell.PowerPlatform.Dataverse'

        # A URL to an icon representing this module.
        # IconUri = ''

        # ReleaseNotes of this module
        ReleaseNotes = '## [1.0.0] - 2026-09-21

First public release (PowerShell Gallery). Breaking changes against the internal 0.1.0 are listed under **Changed**.

### Added
- **Upsert and alternate keys.** `Set-PSDataverseRecord -Key @{ ... } -Upsert` creates or updates
  a record addressed by an alternate key and returns a `DataverseUpsertResult` (`Id`,
  `RecordCreated`). `Get-`, `Set-`, `Remove-` and `Test-PSDataverseRecord` all accept `-Key`
  instead of `-Id`. Batch and transaction operations gained `Action = ''Upsert''` and a `Key`
  entry for Update/Upsert/Delete. This is the primitive an idempotent sync is built on.
- **Lookups without SDK types.** Any attribute value written as
  `@{ LogicalName = ''account''; Id = $guid }` or
  `@{ LogicalName = ''it3c_company''; Key = @{ it3c_name = ''Acme'' } }` becomes an
  `EntityReference` - the SDK equivalent of an OData `@odata.bind`. `PSObject`-wrapped values
  are unwrapped before they reach the SDK serializer.
- **Delegated sign-in with a portable token cache.** `Connect-PSDataverse -Delegated` signs a
  user in through MSAL with an *in-memory* cache; `Get-PSDataverseTokenCache` exports it as
  one opaque string and `-TokenCache` seeds the next session with it. The refresh token thus
  lives wherever the caller keeps secrets (Azure Key Vault via PSDataRepository, for
  instance), which is what Dataverse for Teams - no application users, no premium licence -
  requires. `-LoginMode Silent` makes unattended runs fail fast instead of prompting;
  `Interactive` / `DeviceCode` cover the one-time bootstrap. The cache survives
  `Disconnect-PSDataverse` so it can be persisted after the work is done.
- **Isystem.AzAuth authentication.** `Connect-PSDataverse -AuthMode` acquires tokens through
  `Isystem.AzAuth.Core` with the same mode names PSDataRepository uses: `ClientSecret`,
  `ClientCertificate` (thumbprint, file or `X509Certificate2`), `ManagedIdentity`,
  `WorkloadIdentity`, `NonInteractive` (Azure.Identity default chain), `Interactive`,
  `DeviceCode` and `Cache` (named on-disk MSAL cache). Device-code prompts are relayed to the
  host from the pipeline thread.
- **Structured batch results.** `DataverseBatchResult.Items` carries one
  `DataverseBatchItemResult` per operation - `Index`, `Action`, `LogicalName`, the record
  `Id` (created, upserted or targeted), `Succeeded`, `RecordCreated`, `ErrorCode` and
  `Message`. Operations that never ran because an earlier one faulted (without
  `-ContinueOnError`) are reported as such instead of vanishing.
- `Get-PSDataverseConnection` reports `OrganizationFriendlyName`, `OrganizationId`,
  `EnvironmentId`, `Identity`, `AuthenticationType` and `HasTokenCache`.
- `Get-PSDataverseRecordCount -PrimaryIdAttribute` for tables whose primary key does not
  follow the `{logicalname}id` convention.
- `net10.0` build next to `net9.0`; the new `.psm1` loader picks `bin/<tfm>/` for the running
  PowerShell (7.5 → net9.0, 7.6+ → net10.0), the same way PSSqlRepository and
  PSDataRepository do, so side-by-side modules share one `Microsoft.Extensions.*` major.
- Assemblies are strong-named (public key token `9dfdba2f30eafd53`); see SECURITY.md for what
  that does and does not protect.
- `build/Update-MamlSyntax.ps1` regenerates the MAML syntax blocks from cmdlet metadata so a
  parameter change cannot drift from the shipped help.
- Release pipeline: GitVersion 6.7, Conventional Commits check on pull requests, NuGet
  vulnerability gate, CycloneDX SBOM artifact, strong-name validation of the staged module,
  optional Authenticode signing, publish to Azure Artifacts, the GitHub mirror and the
  PowerShell Gallery from `v*` tags.

### Changed
- **BREAKING - per-record cmdlets raise non-terminating errors.** `Get-`, `New-`, `Set-`,
  `Remove-` and `Test-PSDataverseRecord` now `WriteError` instead of terminating the pipeline,
  so `$ids | Get-PSDataverseRecord` reports one missing record and continues; use
  `-ErrorAction Stop` for the old behaviour. Connection, query, batch and transaction failures
  stay terminating.
- **BREAKING - `Invoke-PSDataverseTransaction` returns a `DataverseBatchResult`** (was the
  operation count) so callers get the ids of created records.
- `Invoke-PSDataverseFetchXml -All` strips a `top` attribute with a warning and refuses
  aggregate queries with a clear error instead of letting Dataverse fail the request.
- `Connect-PSDataverse` reports invalid parameter combinations as `InvalidArgument`
  (`DataverseInvalidConnectionParameter`) rather than as a connection failure.
- The module package no longer carries PowerShell host runtime bits and MSAL satellite
  resources (32 MB → 13 MB per target).

### Fixed
- `tests/general/strings.Tests.ps1` had executed zero tests since February 2026: the assembly
  path was wrong for a `bin/`-based root module and the `::ResourceManager` access on an
  internal type yielded `$null`. `tests/pester.ps1` now counts container-level discovery
  failures, so a broken test file can no longer pass CI silently.
- `tests/general/FileIntegrity.Tests.ps1` had a syntax error and never ran.
- `global.json` pinned `10.0.100` with `latestPatch`, which refused every other 10.0.x SDK.
- The committed `TestResults/` folder is gone and ignored.
'


        # Prerelease string of this module
        # Prerelease = ''

        # Flag to indicate whether the module requires explicit user acceptance for install/update/save
        # RequireLicenseAcceptance = $false

        # External dependent modules of this module
        # ExternalModuleDependencies = @()

    } # End of PSData hashtable

 } # End of PrivateData hashtable

# HelpInfo URI of this module
# HelpInfoURI = ''

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}