TokenShift Enterprise — Installation, Distribution, and Update
- Installed via
install-mdm-template.sh(macOS + Linux) orinstall-mdm-template-win.ps1(Windows), deployed by the customer’s MDM, or fetched from the PointFive app. - One-time enrollment manifest — a few fields of plain JSON, deployed by MDM.
- All data is hybrid-encrypted on the device against PointFive’s public key (pinned in the binary); only PointFive’s KMS holds the matching private key.
- PointFive can control which release version is offered to a given client. PointFive cannot push configuration, rules, or behaviour changes to running clients.
1. What PointFive can and can’t push remotely
Section titled “1. What PointFive can and can’t push remotely”PointFive controls release availability — which version is offered, when, to which fraction of clients. PointFive does not control rules, configuration, opt-out, or any per-fleet behaviour at runtime — those are baked into the binary and the enrollment manifest at install time.
- No remote policy push. All config is install-time.
- No remote rule update. Rules ship in the binary.
- No remote opt-out. A user opts out by changing local config; an admin opts out by redeploying the manifest or uninstalling via MDM.
- No audit-event stream. “Who changed what” lives in the customer’s MDM audit log.
2. Distribution channels
Section titled “2. Distribution channels”| Platform | Primary channel | MDM integration |
|---|---|---|
| macOS | install-mdm-template.sh from the PointFive app | Jamf, Mosyle, Kandji, JumpCloud |
| Linux (Debian/Ubuntu) | install-mdm-template.sh from the PointFive app | Ansible, Salt, Chef, JumpCloud, SCCM |
| Linux (RHEL/Fedora/Amazon) | install-mdm-template.sh from the PointFive app | same |
| Windows | install-mdm-template-win.ps1 from the PointFive app | Intune |
Cross-compiled artifacts for linux/darwin × amd64/arm64 and windows/amd64.
Coverage on a shared machine
Section titled “Coverage on a shared machine”A root-triggered install — install-mdm-template.sh pushed
by MDM/Ansible — installs every eligible user on the endpoint, each into their own
user-owned ~/.tokenshift store, placed and enrolled as that user. Eligibility requires a
resolvable account with a human-range UID (/etc/login.defs UID_MIN/UID_MAX; ≥501 on
macOS), a real login shell, and a home directory it owns; service and system accounts are
skipped with a logged reason. TOKENSHIFT_BEARER_TOKEN carries the API key generated in the
PointFive app and is required — the run aborts before installing anything if it is unset, or
if it is not a well-formed tenant API key (at least 82 characters, p5ts_ prefix, letters, digits and underscores only).
TOKENSHIFT_EXCLUDE_USERS (space- or comma-separated glob
patterns matched against the username, e.g. svc_*) narrows the set, and
TOKENSHIFT_MAX_USERS caps a single run at 10 users — past the cap the first 10
install and the run reports failure, so a shared machine surfaces instead of installing
silently. Nothing is installed to /usr/local/bin — binaries are per-user so self-update
needs no root, and a leftover symlink from an earlier version is removed. The run result is
the exit code and stdout; for inventory, each installed user carries a one-line verdict at
~/.tokenshift/install-status, read by a root inventory script. No device-wide status file
is written — a fixed path in a world-writable directory could be pre-created by a local user
to report the endpoint as compliant when nothing was installed.
A single push only covers accounts present at that moment, so schedule the install on a
recurring trigger (~24h) to pick up users added later; every step is idempotent. The scheduled
run needs TOKENSHIFT_BEARER_TOKEN in its environment like any other — a trigger that omits it
aborts at the config step, so the re-placement and hook re-wiring that the schedule exists for
stop happening.
Windows is per-user and admin-free instead. install-mdm-template-win.ps1 installs the
account that runs it and no other, so there is no eligibility scan, no
TOKENSHIFT_EXCLUDE_USERS, and no TOKENSHIFT_MAX_USERS cap; a shared machine is covered by
assigning the script in user context, not by enumerating accounts. Service SIDs
(S-1-5-18/-19/-20) are refused. The store is %USERPROFILE%\.tokenshift, and it carries
the same install-<stamp>.log + install-status pair, so one inventory query reads every OS.
3. Code signing
Section titled “3. Code signing”| Platform | Signing |
|---|---|
| macOS | Apple Developer ID + notarization. Gatekeeper blocks unsigned binaries. |
| Linux | Binary signature verified against a key pinned in the binary. |
| Windows | Authenticode via Azure Artifact Signing. Publisher CN=POINTFIVE LTD, chaining to Microsoft Identity Verification Root Certificate Authority 2020. |
Verification at install time
Section titled “Verification at install time”The install script verifies the artifact before it places anything, and a rejection exits 45 having installed nothing:
- macOS —
codesignon the extracted binary, against Apple Developer ID TeamJP73DS6HZP - Linux — minisign on the tarball, against a key pinned in the script
- Windows — Authenticode on the extracted
.exe, fail-closed on every one of:StatusisValid, the signature carries an RFC3161 timestamp, the subject isCN=POINTFIVE LTD, and the signer’s EKU holds the artifact-signing marker plus an allowlisted identity OID
Every arm also checks the archive’s sha256, which fails closed on its own.
TOKENSHIFT_REQUIRE_SIG_VERIFICATION=false downgrades a rejection to a logged warning and
records sig=skipped — the check still runs and still logs its result. It exists to recover
from a fleet-wide false rejection. It is insecure by design; the artifact is then
unverified.
The one-line verdict at install-status carries sig=verified|skipped|rejected|unchecked on
every OS, so a single inventory query reports signature posture across the fleet.
On Windows the certificate chain root is logged, and flagged when it differs from the expected Microsoft root — but it never decides the install. Microsoft advises against requiring a specific CA, and is rotating one in October 2026.
Update signatures are a separate contract
Section titled “Update signatures are a separate contract”Auto-update artifacts carry an additional signature; the client verifies it against a key pinned in the binary before swapping. A signature mismatch aborts the update. That check is minisign on every OS, Windows included — tokenshift update never re-runs the installer’s Authenticode check. A signed install does not imply a signed update, and the two must not be read as one guarantee.
4. Enrollment
Section titled “4. Enrollment”The customer admin logs into the PointFive app via SSO, picks install-time configuration (tier cap, project hash mode, recovery cache, sample allowlist, sample rate, retention extensions), and clicks Generate manifest. The app returns enrollment.json — field-by-field meaning is in Enrollment → Field reference.
The admin deploys it via MDM as root to the system path so it covers every user on the machine. A per-user variant (tokenshift enroll <path> writing under ~/.tokenshift/) is available for self-serve installs.
No signature, no expiration, no user roster, no public key in the manifest, no ingest URL in the manifest. The public key and ingest URL are pinned in the binary at build time, so manifest tampering grants no decryption capability and no exfiltration path — at worst an attacker can DoS telemetry. Regenerating and redeploying the manifest invalidates a compromised copy.
CLI surface for self-serve installs: Enrollment.
Agent harness hooks
Section titled “Agent harness hooks”The tokenshift binary supports five PreToolUse-style protocols: Claude Code, Cursor, GitHub Copilot CLI, Codex, and opencode. tokenshift install installs and updates the hook entries idempotently; tokenshift uninstall removes them. Prefix any shell command with tokenshift: to skip the rewrite for that command. Hooks always exit 0, so a TokenShift failure never blocks your work.
Two of the five — Cursor and Codex — run the compressing proxy inside a sandbox that can’t write outside the workspace. Compression and telemetry are unaffected, but the local recovery cache isn’t reachable from either, so tokenshift recover has nothing to replay for sessions on those two harnesses. See Data contract → Recovery cache scope.
Local intent classifier
Section titled “Local intent classifier”A second small footprint on the endpoint, separate from the tokenshift binary itself, worth calling out explicitly for anyone inventorying what gets installed:
- What it is: a compact on-device embedding model (
bge-small-en-v1.5) used to classify what a submitted prompt is about (debugging, feature work, research, and so on). A plain keyword-based scorer is the out-of-the-box default and the fallback whenever the model isn’t present — never blocks, never errors. - Process lifecycle: not a persistent system service. A small helper process starts on demand the first time a harness session needs it, and shuts itself down after about an hour of inactivity — it only exists while you’re actively using the harness.
- Disk: nothing, until someone asks for it. The model bundle is not fetched automatically — an admin runs
tokenshift classifier provisiononce, and the artifacts cache under~/.tokenshift/classifier/, verified the same way (sha256 + signature) as the binary’s own auto-update artifacts. Skip it and the classifier stays keyword-only. - Network: none at all until provisioned. Once artifacts are installed, the daemon re-checks for a retrained model at most once every 4 hours, against the same pinned control-plane host the binary already talks to for its own updates — not a new destination to allowlist, and not a per-prompt call.
- Data: prompt text is read locally to produce the classification label; the prompt itself is never transmitted anywhere, including to produce that label. Only the label ships in telemetry (Tier 2+,
enrichment.intent) — see Data contract → Enrichment.
5. Encryption
Section titled “5. Encryption”HTTPS protects in transit only. TokenShift adds per-record hybrid encryption against PointFive’s public key, pinned in the binary at build time. The client never holds anything but the public key, so a compromised laptop or manifest yields no decryption capability. The matching private key lives only in PointFive’s key-management system, with audited access and no plaintext extraction. Key rotation ships a new binary version with both current and next keys pinned. A single PointFive-wide keypair is the default; per-tenant keypairs are available on request for regulated customers.
6. Updates
Section titled “6. Updates”Auto-update is opt-in on the client side: the developer (or the admin’s deploy script) runs tokenshift update, and the binary verifies the artifact’s signature against its pinned key before atomically swapping itself. PointFive never push-applies an update — but PointFive does control which version a given client is offered, ramping rollouts by client bucket and with a kill switch that stops all auto-updates at once.
MDM-managed fleets typically continue to upgrade via MDM at the admin’s pace; auto-update is the path for developer machines that aren’t tightly MDM-managed. The client_state signal reports the running binary version so admins can see staleness.
One Windows constraint follows from where the signature check lives. The offered Windows version can never roll back below the first signed release, v0.8.0 — the Authenticode check ships in the install script, so a script handed an older unsigned build exits 45 and places nothing. A Windows rollback must serve a signed build, not an older one. Installs already on disk are untouched by this, and a tenant re-running an older copy of the script carries no check at all.
7. Version skew
Section titled “7. Version skew”Customers will routinely run multiple versions in their fleet. The backend supports the last several minor versions of each signal’s schema; older versions are rejected at ingest and admins see data dry up via stalled client_state rows. Sunset is the customer’s lever, not PointFive’s — PointFive refuses old versions, the admin pushes the upgrade.
8. Threat model
Section titled “8. Threat model”| Threat | Mitigation |
|---|---|
| Malicious tampered binary substituted for the legitimate one | Code signing on every platform — Apple Developer ID, minisign, Authenticode. The install script verifies before placement and installs nothing on a mismatch. |
| Auto-update artifact tampering | Artifact signature verified against a key pinned in the binary before swap; mismatched signature aborts the update with a sticky failure state, so the same bad version isn’t re-attempted. |
| Malicious enrollment manifest substituted | Maximum impact: attacker changes config (DoS of telemetry), redirects records (which they can’t decrypt), or invalidates tokens. Public key and ingest URL are pinned in the binary, so manifest tampering grants no decryption capability and no exfiltration path. |
| Stolen laptop’s enrollment manifest exfiltrated | Attacker has the tenant credentials and HMAC key. They can send fake records as that tenant (DoS / poisoning dashboards) and compute user_id for guessed emails — but they had to compromise a customer machine first. Mitigation: regenerate the manifest and redeploy. |
| Network MITM | TLS to pinned PointFive root certificates; ingest URL is pinned in the binary. Hybrid encryption means even a successful MITM gets ciphertext only. |
| PointFive ingest breach | Per-record ciphertext; an attacker without access to the private key gets no decryption capability. The ingest service is stateless. |
| PointFive key-management breach | Worst case — private key extracted means in-flight data decryptable until rotation. Compensated by the key-management posture (no plaintext extraction, audited access). |
| PointFive release-signing key compromise | Attacker can sign malicious binaries. Mitigated by OS-level code-signing chains (Apple Developer ID on macOS, Azure Artifact Signing on Windows) — independent of PointFive’s keys. An attacker would need to compromise both. |
| Stale binary running known-vulnerable code | client_state reports version; admins see staleness and drive upgrades. |
Attacker tries to reverse user_id from leaked PointFive data | Without the per-tenant HMAC key (which lives in customer manifests, not on PointFive’s side), unreversible. |
9. Design boundaries
Section titled “9. Design boundaries”Things we deliberately don’t do:
- Remote configuration push. No behaviour-changing control plane.
- Manifest signing. Public key and ingest URL are pinned in the binary; tampering grants no decryption capability.
- Manifest expiration. Regenerating and redeploying the manifest handles compromise, without the operational burden of expiry.
- User roster in manifest. Replaced by local resolution from
git config user.email. - Per-tenant encryption keypairs. Available on request, not the default.
- In-binary crash reporting.
client_statecarries a self-check boolean, nothing more.
Glossary
Section titled “Glossary”- Enrollment manifest — JSON file generated by the PointFive app, deployed via MDM.
- MDM — Mobile Device Management / endpoint management system (Jamf, JumpCloud, Intune, Ansible, etc.).
- Pinned public key — PointFive’s ingest public key, compiled into the binary at build time. Not in the manifest.
- Tenant — A single customer organization.
- Local intent classifier — an on-device model (plus a keyword-based fallback) that labels what a prompt is about. Runs in a short-lived helper process, not a persistent service; never transmits prompt text.