Skip to main content

navig-msstore

Microsoft Store publishing verbs for NAVIG, wrapping the msstore-publish block.

Works on its own — its own CLI, no navig required · v0.7.2 · PyPI

On its own (no navig needed)

pip install navig-msstore
navig-msstore --help   # no navig needed

With navig

pip install navig-msstore
navig mstore --help
Commands
Command What it does
navig mstore auth Configure the msstore CLI from credentials in the vault (or env).
navig mstore configure Write the Store identity (store/identity.json) for an app -- interactive.
navig mstore creds Show which Store credentials resolve, and from where (values never shown).
navig mstore doctor Preflight the whole Store chain: tooling, credentials, block, and (per app) readiness.
navig mstore info Explain how navig mstore relates to the menu and the block.
navig mstore open Open the Microsoft Partner Center dashboard in a browser.
navig mstore package Build the MSIX by driving the app's scripts/create-msix.ps1.
navig mstore publish Upload + commit a Store submission by applying the msstore-publish block.
navig mstore sales Paid sales (paid apps + add-on purchases) from Partner Center. Read-only.
navig mstore show Show an app's Store identity + latest built MSIX.
navig mstore status Show the current submission status via the Microsoft Store Developer CLI.

navig mstore — the full Microsoft Store toolkit for NAVIG.

A standalone first-party plugin (lives in plugins/, not in core). It is the single source of truth for Store operations — configure identity, resolve credentials, package the MSIX, publish, and check status — for any app (via --dir). It wraps the same msstore-publish block (so publishing stays verifiable) without bloating core.

How it mounts (no core edit)

NAVIG's CLI auto-mounts every navig.commands entry point as a top-level navig <verb> (core/navig/cli/registration.py). This package declares:

[project.entry-points."navig.commands"]
mstore = "navig_msstore:app"

so once installed, navig mstore exists. Disable it like any plugin (navig store disable plugin:navig-msstore) — degrade-never-blocks-boot.

Install

pip install -e plugins/navig-msstore      # from the repo root
navig mstore --help

Credentials (never hardcoded)

msstore authenticates with an Azure AD service principal. This plugin resolves each value with a deliberate precedence:

  1. explicit env — NAVIG_MSSTORE_TENANT_ID / _CLIENT_ID / _CLIENT_SECRET (a per-tool override)
  2. the vault — provider partner_center (the Microsoft Partner Center App-Only credential from the navig-harbor connector), then azure; profile connector, then default. Read via the official navig vault get <provider>/<field> --raw seam, which handles the provider/data_key path and the credential profile.
  3. generic Azure env — AZURE_TENANT_ID / _CLIENT_ID / _CLIENT_SECRET, last on purpose: AZURE_* is shared by az-cli / Terraform / etc. and may be a different Azure app, so the deliberate vault creds win over it.
navig mstore creds     # what resolves + from where (partner_center@connector) -- never reveals a value
navig mstore auth      # resolve -> msstore reconfigure

Vault fields expected: partner_center/tenant_id, partner_center/client_id, partner_center/client_secret (profile connector). Override the first-tried source with NAVIG_MSSTORE_VAULT_PROVIDER / NAVIG_MSSTORE_VAULT_PROFILE. creds shows only the source (no values); auth reveals via --raw only to hand the secret to msstore once, never logging it.

Verbs (every one accepts --dir <app>, default: cwd)

Verb What it does
configure write store/identity.json (Store Product ID + MSIX identity) — interactive
auth resolve creds (env/vault) → msstore reconfigure
creds show what resolves + from where (never reveals a value)
package build the MSIX (drives the app's scripts/create-msix.ps1; --build tauri-builds first, --dry-run stages)
publish apply the msstore-publish block (auto product_id from identity.json + latest .msix)
status msstore submission status
show identity + latest built MSIX
open Partner Center dashboard
doctor preflight the whole chain — tooling (msstore, MakeAppx), creds, block, and per-app readiness (--dir)
# full flow for an app (Anchor shown; -C/--dir points at any app)
navig mstore configure -C apps/anchor      # once, from Partner Center
navig mstore auth                          # creds -> msstore
navig mstore package  -C apps/anchor --build
navig mstore publish  -C apps/anchor       # auto product_id + latest .msix
navig mstore status   -C apps/anchor

publish stays sugar over navig apply msstore-publish … --approve publish — the block does the real, receipt-backed, --approve-gated work.

Sale alerts (the cash-register ring)

navig mstore sales [--days 30] [--json] lists paid sales (paid apps and add-on purchases) from Partner Center's analytics API. It is read-only.

Inside navig's daemon the plugin also checks the same data every hour and sends a Sales notification for each new paid sale (Telegram + the deck feed by default); NAVIG OS plays a cash-register ring for it (Settings → Notifications → Sounds, with a Play button). Free downloads never ring. The first check only records what already exists, so switching it on does not ring for past sales.

  • Microsoft reports sales as daily totals, so a ring means "new in your report", not the second someone paid.
  • The analytics API is rate-limited hard; calls are spaced ~2.5 s apart, so a check over 20 apps takes about two minutes.
  • navig config set plugins.msstore.sales_enabled false turns it off; plugins.msstore.sales_interval_min sets the pace (minutes, at least 15).
  • State: ~/.navig/msstore/sales_state.json (what was already counted).
  • Deck routes: GET /api/deck/msstore/sales (status), POST …/sales/check (check now), POST …/sales/test (a pretend sale, to hear the ring), POST …/sales/digest (the daily summary now; it does not count as the day's).

The daily summary. Once a day, at the first check after 09:00 local time, the daemon sends a Daily sales summary (Telegram + the deck feed by default): yesterday's sales by product and the total of the last 7 full days. It is built from the data the hourly check already read, so it costs no extra Partner Center calls, and it never rings. A day with no sales still gets one, so a missing summary means the watcher stopped.

  • navig config set plugins.msstore.sales_digest false turns it off; plugins.msstore.sales_digest_hour moves it (0-23).
  • Quiet hours apply: a summary hour inside them reaches the deck feed only.
  • State: ~/.navig/msstore/digest_state.json (the day the last one went out, and the per-day totals each summary reported), so a restart never sends a second one.
  • Late sales. Microsoft sometimes fills a day in after the fact. Each summary compares the last 7 days with what earlier summaries reported and adds a line such as Arrived late: 4 sales · $26.00 for Wed 7 Oct, so a morning "no sales" is corrected the next day instead of staying wrong.

The Store sales app. The plugin also registers a free Store sales desktop app in NAVIG OS (Money category): a daily chart of sales or revenue (7, 30 or 90 days), per-app and per-add-on totals, every daily summary (late sales marked), and how the hourly check is doing. Each check merges its 7-day window into ~/.navig/msstore/sales_history.json (kept 400 days, never in the ring's state, so nothing old ever rings); the first time, the daemon also loads 90 days in the background so the chart starts full. Routes: GET /api/deck/msstore/sales/history?days=30 and POST /api/deck/msstore/sales/history/backfill ({"days": 90}).

When the check itself fails. After 3 failed checks in a row (about three hours) the daemon sends one Sales check failing alert (Telegram + the deck feed). It says why in plain words — Microsoft refused the sign-in (an expired secret), access was refused, credentials are missing, or Microsoft could not be reached — and what to do. It never forwards Microsoft's raw response. When a check succeeds again it sends one "working again" message; outages shorter than 7 days lose nothing, because every check re-reads the last 7 days.

The three surfaces

Surface Role
Block msstore-publish the portable, verifiable publish primitive (receipt)
Plugin navig mstore the operator surface — all Store logic; wraps the block + workers
Menu npm run menu (per app) a thin interactive front-end that just calls navig mstore verbs

Core stays clean — none of this is a hardcoded core command.

Metadata

Release files for navig-msstore 0.7.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for navig-msstore 0.7.2
File Size Uploaded Provenance
navig_msstore-0.7.2.tar.gz 56.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for navig-msstore 0.7.2
File Interpreter ABI Platform
navig_msstore-0.7.2-py3-none-any.whl Python 3 none any Details

Total release size: 100.7 kB

Security for navig-msstore 0.7.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page