Skip to content

Cannot publish/unlist modules in PSGallery: MarkMichaelis is not an owner of any IntelliTect.* package #117

@MarkMichaelis

Description

@MarkMichaelis

Summary

We currently have no working credential to publish to PowerShell Gallery from this repo. The recently rotated POWERSHELL_GALLERY_API_KEY GitHub Actions secret was minted under the MarkMichaelis PSGallery account, which owns zero packages. The 7 IntelliTect.* packages on PSGallery are all solely owned by a separate single-user PSGallery account named intellitect, and we do not currently have the Microsoft identity that backs that account.

This blocks:

  • Publishing the 2.0.0 versions of IntelliTect.Common, IntelliTect.File, IntelliTect.Git, IntelliTect.CredentialManager, and IntelliTect.PSToolbox
  • Unlisting the 4 retired modules (IntelliTect.ChatGpt, IntelliTect.Google, IntelliTect.PSRestore, IntelliTect.ResharperNugetSearch)
  • The Deploy.yml workflow on main — next run will 403 on every push

Evidence

Check Result
MarkMichaelis PSGallery profile 0 packages, 0 downloads (profile)
intellitect PSGallery profile 7 packages, 19,251 downloads (profile)
Every IntelliTect.* package's <d:Owners> Single value: intellitect (no co-owners)
Manual unlist attempts via the rotated key HTTP 403 on all 4 retired modules (The specified API key … does not have permission to access the specified package.)
Signing in to PSGallery with mark@intellitect.com Lands at MarkMichaelis profile, confirming that email is bound to MarkMichaelis, not intellitect

PSGallery has no organization-account type — every account is a single Microsoft identity (MSA or Entra). The intellitect account is a shared single-user account whose login credential is not known to us at present. PSGallery never exposes account emails publicly, so we cannot externally determine who at IntelliTect originally registered it.

References:

Background

This situation surfaced during the 2.0 modernization work (commit ba90c1d). The prior CI publishes presumably worked because the POWERSHELL_GALLERY_API_KEY secret was historically minted under the intellitect account by whoever originally set it up. When the key was rotated in session work this week, we (incorrectly) generated the replacement under the personal MarkMichaelis account because that is the only PSGallery account whose login credentials we have. PSGallery accepted an IntelliTect.* glob at key-creation time, but the actual ownership check is enforced server-side at API call time — which is where the 403s appear.

Remediation Plan

1. Find the intellitect PSGallery credential

Try likely candidates for the Microsoft identity that backs the intellitect PSGallery account:

  • A shared mailbox or distribution alias (e.g., info@, it@, psgallery@)
  • An older personal address from whoever originally registered the account (check git blame on CONTRIBUTING.md and Publish.ps1 for early contributors)
  • Have IntelliTect IT/M365 admin check Entra/MSA records for accounts whose display name is "intellitect" or whose primary email forwards into the team

Sign into powershellgallery.com with each candidate and check whether the resulting profile is intellitect.

2. Once signed in as intellitect

  • Mint a new scoped API key: scopes Push + Unlist, glob IntelliTect.*, 365-day expiry
  • Overwrite the GitHub secret POWERSHELL_GALLERY_API_KEY (currently broken)
  • Optionally store under Windows Credential Manager target pstoolbox for local Publish.ps1 use

3. Add co-owners so future rotation doesn't require the shared account

While signed in as intellitect, on each package use Manage Owners → Add Owner and enter the PSGallery username (e.g., MarkMichaelis). The invite is delivered to that user's notification email; they click the link to accept. Per the docs, "All package owners are peers" — peer publish/unlist/remove rights.

Packages to update co-ownership on (5 currently maintained, 4 retired):

  • IntelliTect.Common
  • IntelliTect.File (not yet published; co-own after first publish)
  • IntelliTect.Git (not yet published; co-own after first publish)
  • IntelliTect.CredentialManager
  • IntelliTect.PSToolbox
  • IntelliTect.ChatGpt (retired — unlist instead/also)
  • IntelliTect.Google (retired)
  • IntelliTect.PSRestore (retired)
  • IntelliTect.ResharperNugetSearch (retired)

4. If the intellitect credential is genuinely lost

Use the PSGallery Report Abuse / Contact form on a package page to reach PSGallery admins. The docs cover orphaned-account recovery — admins will verify ownership through external channels (Project URL on this repo, IntelliTect company contacts, etc.) before transferring/granting ownership.

5. Publish the 2.0.0 versions

Once a working key is in place, the existing Deploy.yml will publish IntelliTect.Common, IntelliTect.File, IntelliTect.Git, IntelliTect.CredentialManager, and IntelliTect.PSToolbox (umbrella) in dependency order on the next push to main.

6. Unlist the 4 retired modules

Either via the PSGallery UI (signed in as intellitect) or scripted via DELETE https://www.powershellgallery.com/api/v2/package/{id}/{version} with X-NuGet-ApiKey: <key>.

Acceptance Criteria

  • We can identify which Microsoft identity backs the intellitect PSGallery account (or confirm it is unrecoverable)
  • A valid API key with Push + Unlist scope for IntelliTect.* is stored in POWERSHELL_GALLERY_API_KEY
  • At least one personal IntelliTect employee PSGallery account is added as co-owner on each maintained package so future rotation does not require the shared credential
  • Deploy.yml successfully publishes the 2.0.0 versions
  • The 4 retired modules are unlisted from PSGallery search

Notes

  • Update CONTRIBUTING.md once resolved — it currently says "Sign in to powershellgallery.com using the IntelliTect account" but does not name who holds the credential.
  • Consider documenting the canonical credential holder (or process to recover) in an internal IntelliTect runbook, not in this public repo.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions