IntelliTect / IntelliTect/PSToolbox

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

Open
#117 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
PowerShell
Stars
10
Forks
4
PR merge metrics
No merged PRs in 30d

Description

## 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](https://www.powershellgallery.com/profiles/MarkMichaelis)) |
| `intellitect` PSGallery profile | 7 packages, 19,251 downloads ([profile](https://www.powershellgallery.com/profiles/intellitect)) |
| Every `IntelliTect.*` package's `` | 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:
- [Managing your PowerShell Gallery account](https://learn.microsoft.com/en-us/powershell/gallery/how-to/managing-profile/managing-account) — one identity ⇄ one profile
- [Creating a PowerShell Gallery account](https://learn.microsoft.com/en-us/powershell/gallery/how-to/publishing-packages/creating-an-account) — shared-account pattern for orgs
- [Managing Package Owners](https://learn.microsoft.com/en-us/powershell/gallery/how-to/publishing-packages/managing-package-owners) — co-ownership invite by **username**, peer rights, orphaned-account recovery via Report Abuse

## 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](https://www.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](https://www.powershellgallery.com/policies/Contact) / 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: `.

## 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>

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.