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:
- explicit env —
NAVIG_MSSTORE_TENANT_ID/_CLIENT_ID/_CLIENT_SECRET(a per-tool override) - the vault — provider
partner_center(the Microsoft Partner Center App-Only credential from the navig-harbor connector), thenazure; profileconnector, thendefault. Read via the officialnavig vault get <provider>/<field> --rawseam, which handles theprovider/data_keypath and the credential profile. - 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 falseturns it off;plugins.msstore.sales_interval_minsets 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 falseturns it off;plugins.msstore.sales_digest_hourmoves 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| navig_msstore-0.7.2.tar.gz | 56.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.