AzureDevOpsDscNative.psd1

@{
    RootModule           = 'AzureDevOpsDscNative.psm1'

    # Version number of this module.
    #
    # This value is a fallback for local and CI builds only. Released versions are
    # driven by the git tag: the publish workflow sets $env:ModuleVersion from the
    # tag, and the build stamps that value into the packaged manifest instead of this
    # one. Do not hand-edit this to cut a release - push a vX.Y.Z tag.
    moduleVersion      = '1.1.0'

    # ID used to uniquely identify this module
    GUID                 = 'e7eb078e-5e97-42be-ae8f-decb140fc38e'

    # Author of this module
    Author               = 'ZanattaMichael'

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

    # Copyright statement for this module
    Copyright            = 'Copyright the DSC Community contributors and ZanattaMichael. All rights reserved.'

    # Description of the functionality provided by this module
    Description          = 'A fork of the DSC Community AzureDevOpsDsc module with native DSC v3 support: every resource is discoverable and invokable by dsc.exe via the Microsoft.Adapter/PowerShell adapter, using generated adapted resource manifests, without requiring a wrapper resource.'

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

    # Minimum version of the common language runtime (CLR) required by this module
    CLRVersion           = '4.0'

    # Functions to export from this module
    #FunctionsToExport = @()

    # Cmdlets to export from this module
    #CmdletsToExport = @()

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

    # Aliases to export from this module
    AliasesToExport      = @()

    # Import all the 'DSCClassResource', modules as part of this module
    NestedModules        = @()

    DscResourcesToExport = @('AzDoGroupPermission','AzDoOrganizationGroup','AzDoProject','AzDoProjectServices','AzDoProjectGroup','AzDoGroupMember','AzDoGitRepository','AzDoGitPermission','AzDoAreaPermission','AzDoIterationPermission','AzDoWIPTags','AzDoAreaNodes','AzDoIterationNodes','AzDoBranchPolicy','AzDoVariableGroup','AzDoServiceConnection','AzDoPipelineEnvironment','AzDoAgentPool','AzDoAgentQueue','AzDoTeam','AzDoTeamMember','AzDoPipeline','AzDoPipelinePermission','AzDoEnvironmentApproval','AzDoVariableGroupPermission','AzDoServiceConnectionPermission','AzDoAgentPoolPermission','AzDoSecurityNamespacePermission','AzDoArtifactFeed','AzDoArtifactFeedPermission','AzDoDeploymentGroup','AzDoTaskGroup','AzDoOrganizationSettings','AzDoExtension','AzDoAuditStream','AzDoProjectPermission','AzDoEnvironmentPermission','AzDoWiki','AzDoNotificationSubscription','AzDoRepositorySettings','AzDoCheckConfiguration','AzDoTeamSettings','AzDoArtifactFeedSettings','AzDoArtifactFeedView','AzDoProcess','AzDoProcessPermission','AzDoUserEntitlement','AzDoServiceHook','AzDoPipelineSettings','AzDoQueryFolder','AzDoWorkItemQuery','AzDoQueryPermission','AzDoWIPTagHygiene','AzDoSecureFile','AzDoSecureFilePermission','AzDoPipelineFolder','AzDoPipelineFolderPermission','AzDoGroupEntitlement','AzDoServicePrincipalEntitlement','AzDoPicklist','AzDoProcessWorkItemType','AzDoProcessField','AzDoProcessState','AzDoProcessRule','AzDoProcessBehavior')

    RequiredAssemblies   = @()

    # 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 = @{
            # Set to a prerelease string value if the release should be a prerelease.
            Prerelease   = 'preview2'

            # Tags applied to this module. These help with module discovery in online galleries.
            Tags         = @('DesiredStateConfiguration', 'DSC', 'DSCResourceKit', 'DSCResource', 'DSCv3', 'AzureDevOps')

            # A URL to the license for this module.
            LicenseUri   = 'https://github.com/ZanattaMichael/AzureDevOpsDsc/blob/main/LICENSE'

            # A URL to the main website for this project.
            ProjectUri   = 'https://github.com/ZanattaMichael/AzureDevOpsDsc'

            # A URL to an icon representing this module.
            IconUri      = 'https://dsccommunity.org/images/DSC_Logo_300p.png'

            # ReleaseNotes of this module.
            # Per-release notes are generated from the CHANGELOG's [Unreleased] section
            # at build time and attached to the GitHub Release. This link is the fallback
            # shown on the Gallery listing.
            ReleaseNotes = '## [1.1.0-preview2] - 2026-09-18
 
### Added
 
- AzureDevOpsDscNative
  - Added `AzDoQueryFolder`, a resource managing folders in a project''s shared work
    item query tree. Folders are declared in their own right so that queries can
    depend on them, rather than each query creating its own ancestry - which would
    let two queries in the same folder race to create it and make `Test()` results
    depend on apply order. Deleting a query folder in Azure DevOps deletes its whole
    subtree, so removal of a folder that still has children is refused unless
    `AllowRecursiveDelete` is set.
  - Added `AzDoWorkItemQuery`, a resource managing shared work item queries,
    including the WIQL statement, query type, display columns and sort order.
    Changes are applied in place with PATCH rather than by delete-and-recreate,
    because recreating a query changes its id and would silently break any
    dashboard widget, delivery plan or ACL token referencing it. Queries deleted
    earlier are restored from the query recycle bin instead of failing with a name
    conflict.
  - Added the private Queries API functions `Get-DevOpsQuery`, `New-DevOpsQuery`,
    `Update-DevOpsQuery` and `Remove-DevOpsQuery`.
  - Added `AzDoQueryPermission`, a resource managing the ACL on a work item query
    folder via the `WorkItemQueryFolders` security namespace. Permissions are set
    on folders and inherited by the queries beneath them; omitting `QueryPath`
    targets the project''s query root. Removing the ACL on the query root is
    refused, since that token has no parent to inherit from.
  - Added `WorkItemQueryFolders` support to `New-ACLToken`, `ConvertTo-FormattedToken`
    and `Parse-ACLToken`, with the token patterns in the localized data files. The
    token addresses folders by GUID (`$/{projectId}/{folderId}/...`); because the
    project id is a GUID too, the folder chain is extracted from the remainder of
    the token so the project is not read as the first folder.
  - Added the helper `ConvertTo-NormalizedWiql`, which makes WIQL drift detection
    work. The Queries API does not return the WIQL it was given - it re-indents,
    re-wraps, re-cases and appends a semicolon - so comparing the raw strings would
    report drift on every `Test()`, forever, even when nothing had changed.
  - Added the helpers `Format-AzDoQueryPath`, which normalizes the several ways a
    query path can be written (backslashes, leading/trailing and doubled separators)
    into one canonical form, and `Resolve-AzDoQueryPath`, which walks a query path
    and collects the id of each segment - the ids that a `WorkItemQueryFolders` ACL
    token is built from.
  - Added `AzDoWIPTagHygiene`, a companion to `AzDoWIPTags` that detects work item
    tags misaligned against a canonical vocabulary (`Bugfix` beside `Bug`,
    `frontend` beside `Frontend`, `Tech-Debt` beside `Tech Debt`) and corrects them
    by renaming the tag - Azure DevOps merges a tag into an existing one on rename
    and re-tags every affected work item, so a correction costs one API call per
    tag rather than one per work item. Because a merge is irreversible and
    project-wide, the resource defaults to `RemediationAction = ''Report''`, where
    `Test()` reports drift and `Set()` lists the misalignments without changing
    anything. Tags differing only in digits (`Sprint1`/`Sprint2`, `FY24`/`FY25`)
    are never merged at any threshold, tags already in the vocabulary are never
    touched, and `MaxAutoCorrections` caps how much a misconfigured vocabulary can
    rewrite in one run.
  - Added the private API function `Update-WITTags` (tag rename/merge) and the
    helper `Get-AzDoTagMisalignment`, the pure matching logic behind the resource.
  - Added `AzDoSecureFile`, a resource managing the secure files a project makes
    available to its pipelines (certificates, keystores, provisioning profiles).
    Azure DevOps never returns a secure file''s content, so `Test()` confirms the
    file exists and its properties match but cannot detect content drift; set
    `ForceUpload` to replace the content on every run. Since the API cannot update
    content in place, `ForceUpload` deletes and re-uploads, which changes the
    file''s id - so any permission granted against the old id has to be re-applied.
  - Added `AzDoSecureFilePermission`, managing a secure file''s ACL in the `Library`
    security namespace, and extended the `Library` ACL token with the
    `SecureFile/{id}` segment across `New-ACLToken`, `ConvertTo-FormattedToken` and
    the localized token patterns.
  - Fixed `Get-AzDoVariableGroupPermission`: its project-root Library filter matched
    any token without a variable group segment, which now also matches a secure
    file''s token. The filter excludes secure file tokens explicitly.
  - Added the private API functions `List-DevOpsSecureFiles`, `New-DevOpsSecureFile`,
    `Update-DevOpsSecureFile` and `Remove-DevOpsSecureFile`, and a `LiveSecureFiles`
    cache type.
  - Added `AzDoPipelineFolder`, a resource managing the pipeline (build) folder tree.
    Paths are backslash-delimited and normalized, so the several ways a folder path
    can be written are one desired state. Deleting a pipeline folder deletes every
    definition beneath it, so removal is refused unless `AllowRecursiveDelete` is
    set - and refused as well when emptiness cannot be established, rather than
    treating a failed lookup as "empty".
  - Added `AzDoPipelineFolderPermission`, managing a pipeline folder''s ACL in the
    `Build` security namespace, and added the folder token form
    (`{projectId}/{folderPath}`) to `New-ACLToken`, `ConvertTo-FormattedToken`,
    `Parse-ACLToken` and the localized patterns. Previously the `Build` branch
    understood only the definition token form, so folder-level pipeline permissions
    could not be expressed at all - including through `AzDoPipelinePermission`.
  - Added the helper `Format-AzDoPipelineFolderPath` and the private API functions
    `List-DevOpsPipelineFolders`, `New-DevOpsPipelineFolder`,
    `Update-DevOpsPipelineFolder`, `Remove-DevOpsPipelineFolder` and
    `Get-DevOpsPipelineDefinitionsInFolder`.
  - Added `AzDoGroupEntitlement`, a resource managing group licensing rules - the
    access level applied to every member of a group. `AzDoUserEntitlement` assigns
    a level one user at a time, which does not scale to an organization. Changing
    the level re-licenses the group''s members; removing the rule removes nobody
    from the organization, only what the rule granted them.
  - Added `AzDoServicePrincipalEntitlement`, managing service principals and
    managed identities as organization members. Identity is matched by Microsoft
    Entra object id rather than display name, since names are neither unique nor
    stable and a rename would otherwise cause a duplicate to be created. The
    endpoint is a preview API; when an organization does not expose it, the lookup
    reports the entitlement as absent rather than failing the configuration.
  - Added `AzDoPicklist`, a resource managing picklists - the allowed values behind
    picklist-typed custom fields. Picklists are organization-scoped, so one list
    backs fields across processes. Items are replaced wholesale because the update
    endpoint takes the complete list; removing a value does not rewrite work items
    that already carry it, so they keep a value that then fails validation on the
    next edit. The list type is fixed at creation and a mismatch is reported rather
    than silently recreating the list.
  - Added `AzDoProcessWorkItemType`, managing custom and inherited work item types
    on an inherited process. Only inherited processes can be customized; naming a
    system process (Agile, Scrum, Basic, CMMI) is reported with that reason instead
    of failing against the API. Removal is destructive in two different ways - a
    custom type takes its work items with it, an inherited type discards this
    process''s customizations - so both require `AllowDestructiveRemove`, with
    `IsDisabled` offered as the reversible alternative.
  - Added the helper `Resolve-AzDoProcessWorkItemType`, which resolves a process and
    work item type and enforces the "system processes are read-only" rule in one
    place, and the private API functions for picklists and process work item types.
  - Added `AzDoProcessField`, managing fields on a work item type. A field exists at
    two levels and the resource manages the second: the definition (name and type)
    is organization-scoped and shared by every work item type using the field, so
    changing it would change the field everywhere; what is per-type is required,
    default value and read-only. A new custom field''s reference name is assigned by
    Azure DevOps and cannot be chosen, so fields are matched by display name and the
    reference name is read back. Removing a field detaches it rather than deleting
    it - the data on existing work items is retained.
  - Added `AzDoProcessState`, managing custom workflow states. A state''s category
    (`Proposed`, `InProgress`, `Resolved`, `Completed`, `Removed`) is what boards and
    Analytics reason about, and it cannot be changed after creation: a mismatch is
    reported as an error rather than as drift, since recreating the state would
    strand every work item currently in it. Only custom states can be removed, and
    work items in a removed state keep a value that then fails validation.
  - Added the private API functions for process fields and states.
  - Added `AzDoProcessRule`, managing conditional rules on a work item type.
    Conditions and actions are passed through as the API models them rather than
    wrapped, because the vocabulary is large and grows between API versions. Drift
    detection normalizes both sides first: a configu'


        } # End of PSData hashtable

    } # End of PrivateData hashtable
}