Commit Graph

176 Commits

Author SHA1 Message Date
rcourtman c17664b3da Distinguish MSP evaluation issuance from readiness 2026-08-11 14:50:47 +01:00
rcourtman 9449a6909e Make provider MSP evaluation activation attributable 2026-08-11 14:27:29 +01:00
rcourtman 5a865820a6 Prepare v6.2.1 emergency patch release 2026-08-10 00:54:43 +01:00
rcourtman e9904157e7 Prepare v6.2.0 stable release 2026-08-09 10:43:19 +01:00
Richard Courtman 894e0eb213 chore(release): prepare v6.2.0-rc.11 2026-08-08 20:26:15 +01:00
rcourtman 81ccca17a5 Prepare v6.2.0-rc.10 release 2026-08-08 17:34:07 +01:00
rcourtman fbee92614a fix(release): restore verifiable MSP evaluation delivery 2026-08-08 01:04:07 +01:00
rcourtman 4885c378aa Keep the operator .env out of the Traefik container and unhardcode the DNS-01 provider
Traefik took the whole operator .env via env_file, so the internet-facing
container's environment carried CP_ADMIN_KEY and the entitlement signing
private key, neither of which it needs. It now receives only ACME/DNS
material: the CF token by explicit passthrough plus an optional
dns-credentials.env that setup.sh creates 0600.

The same wiring removes the silent Cloudflare-only narrowing: the resolver
provider is now ACME_DNS_PROVIDER (default cloudflare) via Traefik's env
override, the CF token is required only for the default provider, and any
other Traefik dnsChallenge provider supplies its credential variables through
dns-credentials.env. Pinned by
TestProviderMSPTraefikEnvIsMinimalAndDNSProviderOverridable; contract delta
in deployment-installability.
2026-08-07 10:47:13 +01:00
Richard Courtman 8a616b4b56 Prepare v6.2.0-rc.9 release 2026-08-07 10:03:16 +01:00
rcourtman 7c9a572349 chore(ci): stop resurrecting the pulse-agent GHCR package
The agent_runtime verify-only build pointed its registry buildcache at
ghcr.io/<owner>/pulse-agent, a package no workflow publishes. A cache ref
creates the package it points at, so every release recreated it and the
repository's Packages sidebar advertised an empty pulse-agent entry that
reads like a pullable agent image sitting beside the real pulse,
pulse-control-plane and pulse-chart/pulse packages. The only release tag it
ever carried is a stray v6.0.0-rc.3.

Move the cache to ghcr.io/<owner>/pulse:agent-buildcache, alongside the
runtime stage's existing pulse:buildcache tag, so it lives in the package
that actually ships and shares backend-builder layers with the runtime
build.

TestAgentBuildCacheDoesNotResurrectPulseAgentPackage locks this in. It scans
every workflow for registry-qualified refs to the pulse-agent package,
collapsing ${{ }} expressions first so an interpolated owner cannot hide one
behind its spaces, and asserts both the new cache target and the chart's
published agent image default. Verified red on a restored buildcache ref and
red again on a ref hidden behind ${{ github.repository_owner }}.

Two stale claims corrected while here. The chart values comment said the old
agent.image default was never published, when it did carry v6.0.0-rc.3. The
deployment-installability contract called rcourtman/pulse the only image
publish-docker.yml pushes, when the same workflow also pushes the MSP
pulse-control-plane image. The contract now also forbids buildcache
references to the pulse-agent package, which is what let this regress.

Deleting the orphaned package itself remains a manual GHCR step.
2026-08-06 10:48:05 +01:00
rcourtman f5c492357e Revert "Prepare v6.2.0-rc.9 release"
Restore RC8 release metadata and remove the unpublished RC9 packet after cancelling its release workflow.
2026-08-05 22:18:52 +01:00
rcourtman c16a9901b4 Prepare v6.2.0-rc.9 release
Advance the governed install, Docker, and Helm metadata together; add the RC9 release packet for the post-RC8 notification, lifecycle, and resource-read fixes; and record the existing mobile-candidate compatibility decision.
2026-08-05 21:34:53 +01:00
rcourtman fdcb223e6f Prepare v6.2.0-rc.8 release 2026-08-05 14:43:37 +01:00
rcourtman 27948c6de4 Prepare v6.2.0-rc.7 release 2026-08-03 22:17:03 +01:00
rcourtman 9d9f13e7b0 Self-issue the MSP evaluation licence, and fix two things it exposed
The evaluation mode added earlier today was hollow. An unlicensed control
plane starts, but release-build client runtimes only trust entitlement
leases chained to a Pulse-signed licence, so its client workspaces ran
without the capabilities the provider was evaluating. Standing the stack
up proved the portal and the isolation boundary and nothing else.

setup.sh now requests a capped evaluation licence from the licence server
when no licence path is set, sending only the public half of the key it
generated locally. It degrades rather than blocks: a missing key, an
unreachable server, or a licence-free response leaves the install
unlicensed with an explicit warning, an existing licence on disk is
reused, and PULSE_PROVIDER_MSP_SKIP_EVAL_LICENSE skips it for air-gapped
hosts. Guarded with an if-test rather than a trailing true inside the
command substitution, because the derive helper calls die and exit in a
subshell is not a status that can be caught, so setup.sh aborted under
set -e.

Second fix. The lease capability ceiling was selected by licence
presence, so an unlicensed provider control plane fell through to the
Pulse-hosted branch and minted leases claiming relay, mobile and push,
which a provider deployment cannot serve and which previously caused
repeating relay registration failures in client runtimes. The ceiling now
follows hosting via SetProviderHosted. providerChained keeps its narrower
meaning of having a licence available to embed.

Third. Corrects a sentence I wrote into cloud-paid.md this afternoon
claiming msp_eval carries the same MSP capabilities. A plan version
selects the workspace cap; it does not entitle a workspace.

The regression test was negative-tested by reverting the ceiling selector
and confirming it catches relay. All three setup.sh degradation paths
were exercised directly. Licence server side is pulse-pro 7f6a319 and is
not live until the next deploy-license-server run.
2026-08-03 18:14:05 +01:00
rcourtman 6be2af1c19 Let providers evaluate MSP without asking permission first
Two mandatory round-trips stood between an interested MSP and their first
screen, and neither was technical.

setup.sh required four image digests shipped as literal <pin>
placeholders, so the only way to get them was to ask. All four images are
publicly readable, so there was never anything to hand out. setup.sh now
resolves each blank pin to an immutable digest from its published tag via
buildx imagetools and writes it back to .env; hand-set values are left
alone.

setup.sh then died outright without a licence file, so nobody could start
the stack, create a workspace, or see the portal until a human minted a
licence for them. The control plane already ran unlicensed via
ProviderMSPPlanSourceEnvFallback; only the installer refused. A licence
path that is set but missing is still a hard failure, since that is a
misconfiguration rather than a choice.

Unlicensed now means evaluation rather than the cheapest paid tier. The
env fallback defaulted to msp_starter, handing every unlicensed
deployment the full 5-client Starter allowance and leaving no boundary
between evaluating and buying. Adds msp_eval at 2 workspaces: same
capabilities, smaller cap, not purchasable, not on the public ladder.

An isolation guarantee is the one claim a provider cannot evaluate from a
screenshot, and both MSP leads this year went quiet at exactly this step.

Contracts: cloud-paid records the unlicensed plan rule and the
strictly-below-paid invariant; deployment-installability records
credential-free, correspondence-free installability.

Verification: TestMSPEvalCapStaysBelowCheapestPaidTier,
TestCanonicalizePlanVersion_MSPEval,
TestProviderMSPSetupScriptSupportsUnlicensedEvaluation. The last was
negative-tested by reintroducing a <pin> placeholder and confirming it
fails. ensure_image_pins exercised against the live registries.
licensing, cloudcp, control-plane and installtests all green.
2026-08-03 16:31:24 +01:00
rcourtman 28dd1c0398 Prepare v6.2.0-rc.6 release 2026-08-01 21:19:59 +01:00
courtmanr@gmail.com 372a969a76 Prepare v6.2.0-rc.5 release 2026-07-31 17:47:52 +01:00
courtmanr@gmail.com e13f42667e feat(kubernetes): add OpenShift-safe Helm profile 2026-07-30 17:38:02 +01:00
courtmanr@gmail.com f4dd8096aa Prepare v6.2.0-rc.4 release
Fourth candidate on the v6.2.0 line, superseding v6.2.0-rc.3 and still following stable v6.1.2. This hardening cut includes action recovery, kiosk containment, alert and notification accounting, node-restricted Proxmox storage, container-runtime selection, and host CPU sampling fixes that landed after rc.3. Version pins move to 6.2.0-rc.4 across the repo root, Docker bootstrap defaults, and Helm metadata; stable install pointers remain on v6.1.2 until governed promotion.
2026-07-29 14:49:51 +01:00
courtmanr@gmail.com d1ee6e928b Fix multi-organization Proxmox connection identity 2026-07-28 17:15:54 +01:00
rcourtman 16ff5544c1 Prepare v6.2.0-rc.2 release
Second candidate on the v6.2.0 line, superseding v6.2.0-rc.1 and still
following stable v6.1.2. This is a hardening and bugfix candidate:
auto-update reliability including in-place migration of already-deployed
update units, PBS backup attribution across multiple Proxmox clusters,
Proxmox installer registration including per-canonical-type bootstrap
grants on combined PVE+PBS hosts, Patrol readiness streaming transport
plus a completed-verdict readiness gate, discovery-policy DNS and SSH
retry churn, explicit per-metric threshold off toggles, request-derived
SSO callback URLs, and the new Entra ID SSO guide. Version pins move to
6.2.0-rc.2 across the repo root, Docker bootstrap defaults, and Helm
metadata per the deployment-installability contract; stable install
pointers remain on v6.1.2 until governed promotion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 16:05:56 +01:00
courtmanr@gmail.com f45c08902e Prepare v6.2.0-rc.1 release
First candidate on the v6.2.0 line, following stable v6.1.2. Carries
the External Probes Pro feature, the three-part multi-site Proxmox
identity isolation work, cloned machine-id collapse detection,
unattended-update service recovery, the TrueNAS same-host redirect
follow, and verified telemetry outcomes. Version pins move to
6.2.0-rc.1 across the repo root, Docker bootstrap defaults, and Helm
metadata per the deployment-installability contract; stable install
pointers remain on v6.1.2 until governed promotion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 14:08:29 +01:00
courtmanr@gmail.com e405270e89 Prepare v6.1.2 stable patch release 2026-07-26 20:38:42 +01:00
rcourtman 781e168e34 Prepare v6.1.1 emergency patch release 2026-07-23 13:28:17 +01:00
rcourtman 984ca06918 Prepare v6.1.0 stable release 2026-07-22 15:05:37 +01:00
rcourtman d3070ce1cb Prepare v6.1.0-rc.5 release 2026-07-22 11:28:45 +01:00
rcourtman 52ed884640 Prepare v6.1.0-rc.4 release 2026-07-19 15:52:42 +01:00
rcourtman b9eb7c3241 Prepare v6.1.0-rc.3 release 2026-07-18 16:56:00 +01:00
rcourtman a857c7e783 Prepare v6.1.0-rc.2 release 2026-07-16 23:45:31 +01:00
rcourtman e2ec59a840 Prepare v6.1.0 RC1 release 2026-07-13 18:35:08 +01:00
rcourtman 92ea590000 Prepare v6.0.6 RC1 release packet 2026-07-10 21:39:03 +01:00
rcourtman 0e40ec07cb Make the provider MSP portal honest and self-sufficient without an email provider
Exercised the full provider portal as a pilot MSP would and fixed what
made it feel broken:

- The signed-out portal promised "a sign-in link is on the way" even when
  the control plane has no email provider (the bundle default), and team
  invitations silently sent nothing. The portal bootstrap now carries
  email_sign_in_available and provider_hosted_mode; the sign-in page shows
  the host command that actually prints a link, and the invite panel says
  invitation emails are not sent and how to hand over a link instead.
- New "provider-msp portal-link --email" CLI mints a one-time portal link
  for an account member or pending invitee, so teammates can sign in at
  all on email-less installs (bootstrap only covers the owner).
- Portal sessions were fixed at 12h; CP_SESSION_TTL now configures them
  and provider-hosted MSP mode defaults to 7 days.
- Creating a client past the license cap showed a generic "Failed to
  create workspace." toast: the limit error is now a JSON payload with
  current/limit, the API client no longer drops non-JSON error bodies
  (double body read), and the toast explains the license limit.
- Copy polish: provider-mode sign-in intro (no refunds/privacy register),
  least-privilege default invite role, queue tile label matches "Client
  onboarding", softer Support tab with a docs/MSP.md pointer, setup.sh
  summary now prints the bootstrap next step and day-2 sign-in commands,
  .env.example and docs/MSP.md document portal sign-in and sessions.

Contracts updated (cloud-paid, api-contracts, deployment-installability,
security-privacy) with verification pins in tenant_handlers_test,
config_test, magiclink_test, and provider_msp_deploy_test.

Verified live against a dockerless control plane: portal-link for an
invitee redeems, promotes the invitation, and sets a 7-day session;
the at-cap toast shows the license copy; portal vitest suite and
cloudcp/auth/account/installtests Go suites pass.
2026-07-10 11:22:57 +01:00
rcourtman 255c7c23d4 Modernize Unified Agent lifecycle and platform support 2026-07-09 23:20:35 +01:00
rcourtman 6999ca0119 Prepare 6.0.5 release 2026-07-09 11:52:28 +01:00
rcourtman 0d787a4b1f Prepare v6.0.5 RC4 release packet
Refs #1535
2026-07-08 13:10:06 +01:00
rcourtman 0ff922ca16 Prepare v6.0.5 RC3 release packet
Refs #1535
2026-07-07 16:48:12 +01:00
rcourtman e1cddca2d1 Prepare v6.0.5 RC2 release packet
Refs #1470

Refs #1471

Refs #1476

Refs #1483

Refs #1511

Refs #1515

Refs #1516

Refs #1524

Refs #1533

Refs #1534
2026-07-07 10:50:49 +01:00
rcourtman dded079297 Prepare v6.0.5 RC1 release packet
Refs #1530

Refs #1531

Refs #1471
2026-07-07 00:12:09 +01:00
rcourtman 41a99c1a03 Prepare v6.0.5 patch release
Refs #1530

Refs #1531
2026-07-06 23:29:17 +01:00
rcourtman 1d7fa6c4bf Prepare v6.0.4 release 2026-07-06 16:50:59 +01:00
rcourtman 44af57b8fc Prepare v6.0.4-rc.2 support build
Package the audit timestamp compatibility fix for private Pro support validation.
2026-07-06 09:22:44 +01:00
rcourtman 6212eecf12 Align Docker defaults with v6.0.4-rc.1
Pin Docker install defaults and Helm metadata to the support prerelease version.
2026-07-05 21:10:47 +01:00
rcourtman c384d5e0c8 Prepare v6.0.3 patch release 2026-07-05 11:07:27 +01:00
rcourtman c0ae794dc9 Prepare v6.0.2 release 2026-07-04 23:19:42 +01:00
rcourtman 6becdbf9db Auto-update Helm chart documentation 2026-07-04 20:03:41 +00:00
rcourtman 84ad973540 Prepare v6.0.1 patch release
- bump release, Docker, and Helm metadata to 6.0.1

- add committed v6.0.1 patch release notes and changelog

- allow stable patch hotfix releases without a fabricated same-version prerelease tag
2026-07-04 19:32:01 +01:00
rcourtman e3dba105a7 Build control-plane image with embedded frontend assets 2026-07-04 14:46:53 +01:00
rcourtman 48e1efece7 Use patched Go toolchain for v6 release 2026-06-14 18:22:26 +01:00
rcourtman a17882458a Rename CP_TRIAL_ACTIVATION_PRIVATE_KEY to CP_ENTITLEMENT_SIGNING_PRIVATE_KEY in the provider MSP bundle
The variable signs hosted entitlement leases; the trial-activation name is
left over from the retired trial era and reads as trial machinery to an
operator generating their licensing root key. The provider MSP bundle has
no installed base yet, so the canonical rename is free today and frozen
the moment the first design partner installs.

- Control plane reads CP_ENTITLEMENT_SIGNING_PRIVATE_KEY first and falls
  back to CP_TRIAL_ACTIVATION_PRIVATE_KEY, so existing Pulse-hosted cloud
  deployments (deploy/cloud, hibernated snapshot) keep working unchanged.
- deploy/provider-msp (.env.example, compose, setup.sh), MSP.md, and the
  install-test pins use the canonical name; error messages name it too.
- deploy/cloud intentionally keeps the legacy name: that stack historically
  signed hosted trial activations, and its snapshot predates the rename.
2026-06-10 14:08:52 +01:00