Arc Forge Labs Docs v2026.10.2

Microsoft Store Automation

This runbook covers the non-secret automation pieces for publishing Dictate through the Microsoft Store for the existing Partner Center product. Deployment credential boundaries and approval requirements are tracked in deployment-security.md.

Current Partner Center Identity

  • Product name: Arc Forge Dictate
  • Product type: MSIX or PWA app
  • Store ID / product ID: 9P5S7747V0BP
  • Package/Identity/Name: ArcForgeLabs.ArcForgeDictate
  • Package/Identity/Publisher: CN=56989B1A-E9FD-45E0-827B-FDB65D3C9B3C
  • Package/Properties/PublisherDisplayName: Arc Forge Labs
  • Package Family Name (PFN): ArcForgeLabs.ArcForgeDictate_tbf7er950vsxw
  • Package SID: S-1-15-2-414942928-860362531-3808921871-2325232450-2546095560-3460849545-2812936032
  • Partner Center app role: Manager(Windows)
  • Store publication status changes in Partner Center. Do not hard-code transient submission IDs, draft package names, certification stages, or internal account identifiers in this public repository.

Store Package Builder

  • MSIX manifest template: packaging/msix/Package.appxmanifest.in
  • MSIX build script: scripts/build-windows-msix-store.ps1
  • Manual MSIX workflow: .github/workflows/windows-msix-store-bundle.yml
  • Manual MSIX publish workflow: .github/workflows/msstore-publish-msix.yml
  • Output pattern: packaging/msix/out/ArcForgeDictate_<version>_x64.msix

The MSIX manifest is pinned to the reserved Partner Center identity. The builder uses tauri build --no-bundle, stages dictate-ui-shell.exe and engine\dictate-engine.exe, renders the four-part MSIX version from tauri.conf.json, and packs the loose layout with Microsoft winapp.

The Store reserves the fourth version part, so it is always 0. The day and the same-day release number share the third part: 2026.9.25 packs as 2026.9.2500.0 and 2026.9.25-1 as 2026.9.2501.0. Unstable versions are rejected; the Store is stable-only.

A draft upload fails if Partner Center already holds a submission created by hand there. Delete that submission in Partner Center, then rerun mode=draft.

GitHub Actions Wiring

Add these repository variables in GitHub Actions. Keep the values in repository settings, not in committed docs:

  • MSSTORE_TENANT_ID
  • MSSTORE_CLIENT_ID
  • MSSTORE_SELLER_ID

Add this repository secret:

  • MSSTORE_CLIENT_SECRET: the Partner Center Publisher app client secret value.

Do not store the client secret in this repository.

Current GitHub Actions state:

  • Repository variables are set for tenant ID, client ID, and seller ID.
  • MSSTORE_CLIENT_SECRET is set as a GitHub Actions repository secret.
  • msstore-publish-msix.yml status mode verifies credentials and current Store submission status without creating or committing a package.

Smoke Workflow

Use .github/workflows/msstore-api-smoke.yml to verify credentials.

Auth-only smoke:

gh workflow run msstore-api-smoke.yml

After this workflow is committed to the default branch, query the reserved MSIX/PWA product:

gh workflow run msstore-api-smoke.yml -f product_id=9P5S7747V0BP -f query=legacy-app
gh workflow run msstore-api-smoke.yml -f query=legacy-apps

Use .github/workflows/msstore-publish-msix.yml for the guarded package update path.

Read-only status:

gh workflow run msstore-publish-msix.yml -f mode=status -f product_id=9P5S7747V0BP

Upload a newly built MSIX into the current draft without committing it:

gh workflow run msstore-publish-msix.yml -f mode=draft -f product_id=9P5S7747V0BP

Commit the current draft to Microsoft certification:

gh workflow run msstore-publish-msix.yml -f mode=publish -f product_id=9P5S7747V0BP

mode=draft uploads a newly built MSIX into a Store draft without committing it. Review that draft in Partner Center before running mode=publish, which commits the current draft and polls Microsoft certification.

Updating the listing

The Store listing text and screenshots live in the repo and ship with every draft:

  • Text: docs/msstore-listing.md sections Short Description, Description, Product Features, Release Notes and Keywords.
  • Screenshots: docs/msstore/assets/screenshots/, in the order the README there lists them, with its captions.

mode=draft runs scripts/msstore-submit.py legacy-draft, which creates one API submission, queues the new MSIX (the previous package is marked for removal), replaces the en-us text and screenshots (logos are kept), uploads the package and screenshots in one zip, and reads the draft back to check the package and description landed. It never commits. To change only the listing, edit those files, merge, and run a draft; the package is rebuilt from master either way.

Local Smoke

Set the same environment variables locally, then run:

python scripts/msstore-submit.py auth-check
python scripts/msstore-submit.py legacy-auth-check
python scripts/msstore-submit.py legacy-apps
MSSTORE_PRODUCT_ID=9P5S7747V0BP python scripts/msstore-submit.py legacy-app

The script never prints access tokens or client secrets.

Submission Discipline

Microsoft warns that once a submission is created through the API, edits to that same submission should continue through the API rather than Partner Center. For Dictate:

  1. Use the API smoke/status workflow to confirm credentials and product access.
  2. Run the Windows release gate against the GitHub release you are about to ship: scripts/windows-vm-release-gate.sh --tag vYYYY.M.N. It installs the published setup.exe on the win11-gpu VM, launches it in the signed-in session, checks the engine's /api/health version, and uninstalls. Do not draft if it fails. See windows-11.md.
  3. Use msstore-publish-msix.yml with mode=draft to create/update the Store draft package.
  4. Review the draft in Partner Center.
  5. Use mode=publish only when that draft should be submitted for Microsoft certification.
  6. Use API-created submissions consistently for future automated updates.

Use msstore-listing.md for the first listing copy, privacy/certification notes, screenshots checklist, and remaining pre-submit requirements.

API Notes

The current helper targets the newer Store API surface documented by Microsoft for MSI/EXE submissions. The reserved product is an MSIX or PWA app; Microsoft still documents the older Store services API for registered UWP/MSIX apps at https://manage.devcenter.microsoft.com/v1.0/my/applications. Validate the correct API path for 9P5S7747V0BP after the first manual submission is accepted, or create a separate MSI/EXE product if we choose the Tauri installer path.

The MSIX/UWP Store services API uses:

  • Token endpoint: https://login.microsoftonline.com/<tenant-id>/oauth2/token
  • Resource: https://manage.devcenter.microsoft.com
  • Base URL: https://manage.devcenter.microsoft.com/v1.0/my

The newer Store Submission API uses:

  • Token endpoint: https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
  • Scope: https://api.store.microsoft.com/.default
  • Base URL: https://api.store.microsoft.com
  • Required request header: X-Seller-Account-Id

The current helper supports:

  • auth-check
  • legacy-auth-check
  • legacy-apps
  • legacy-app
  • status
  • metadata
  • guarded submit --confirm-submit
  • legacy-draft (MSIX draft with package, listing text and screenshots; no commit)

mode=draft uploads through scripts/msstore-submit.py legacy-draft (see "Updating the listing"). mode=publish and mode=status use the Microsoft Store Developer CLI: msstore submission publish <productId> commits the draft and msstore submission poll follows certification.

An earlier draft step used msstore publish --inputDirectory <dir> with no project path. The CLI then inspected the working directory, saw package.json, treated the repo as an Electron app and uploaded without attaching the package; the Store re-published the previous package and reported success. That happened with the first September 2026 submission.