A Licence is a small JSON file signed with Ed25519 by Pulsover. It
names the customer, the Databricks account ID, the install it is issued
to (Install Key fingerprint), the Tier, optional features, the maximum
number of Accounts, the issue and expiry dates and the Grace Period
length (domain/licence/licence.go).
internal/licencekeys/keyring.json). Nothing is sent to
Pulsover to check it.bundles/<fingerprint>/licence.lic.age); the rules
job fetches, decrypts, verifies and stores it in the product secret
scope (key licence). An older file never replaces a newer
one. You can also import it by hand with
pulsobot-installer rules import.| Where | What it gates |
|---|---|
| API App (re-read every 5 minutes) | Paid routes: submitting, retrying, validating and promoting
Remediation Orders; LLM re-analysis; Monitor; the number of active
Accounts. Anything else answers 403
(middleware.RequireLicence) |
| Remediation Agent, Test Agent (at start-up) | Without an Optimize Licence they are dormant: they log it, take no work and exit successfully |
| Deployment Agent (at start-up) | Without an Optimize Licence it starts no new deployment; its safety sweeps (pause, rollback, teardown) still run |
| Rules job | Paid rules are evaluated only with an Optimize Licence |
The job checks exist because anyone with workspace access could
trigger a job directly. Remediation also has a second, independent gate:
the FF_REMEDIATION feature flag. Both must
allow a write; the Licence never replaces the flag. Hiding menus in the
dashboard is a convenience; the server-side checks are the boundary.
Any error while checking (secret unreadable, keyring invalid) fails closed for new work, never for work already in flight.
expires_at: everything the Tier allows.grace_days after
expiry): everything keeps running; the dashboard shows a banner.403.Only the agents that start new work check the Licence: the
Remediation and Test Agents at startup, the Deployment Agent before
claiming a deployment. Without a valid Optimize Licence they log
dormant and exit 0. Work already in flight always finishes:
the Verification Agent and the Cleanup Agent never check the Licence,
rollback and pause sweeps keep running, and cancel / revert routes stay
open (test/architecture/licence_test.go). An expired
Licence never leaves a half-done change on your jobs.
Each public key in the binary's keyring has a key ID
(kid) and a purpose:
| Purpose | Can sign | Where the private key lives |
|---|---|---|
licence |
Licences only | AWS KMS (Ed25519); only the sign-licence workflow's role, behind a human approval, may sign |
bundle |
Paid Rule Set Bundles and the free-template manifest, never a Licence | AWS KMS; only the promote-ruleset workflow's role, behind a human approval, may sign |
free |
Free Rule Set Bundles only, never a Licence or a paid bundle | AWS KMS; only the registration service may sign |
An install accepts a signature only from a key of the expected
purpose. Each key has exactly one IAM role allowed to sign and an
explicit Deny for everyone else, asserted in CI by
tofu test (infra/licence/tests,
infra/registration/tests).
Private keys never leave AWS KMS.
Residual risk: key policy changes. KMS key
administrators keep kms:PutKeyPolicy (without it Terraform
could lock itself out of a key), so a key administrator could rewrite a
policy to grant themselves kms:Sign. Mitigation: few key
administrators, and a CloudTrail alert (EventBridge rule on
PutKeyPolicy, CreateGrant and
ScheduleKeyDeletion for these keys) that notifies the
security owner. Any such change also shows up as drift on the next
tofu plan. Rotation: a new public key ships in a release
next to the old one; once customers have that release, signing switches
to the new key and the old entry gets a retired_at date (a
Licence it signs must have been issued before that date, reason
retired_kid otherwise; the signing tools refuse a retired
key for every artifact); the old key is dropped once no Licence it
signed is still valid. A release check
(pulsobot-licence keyring check) refuses a keyring change
that would strand valid Licences. If a key is ever compromised, it is
disabled in KMS at once and dropped from the keyring in a security
release; still-valid Licences are re-signed with the new key and
re-delivered.
There is no remote kill switch, by design (no call home). What Pulsover can do:
What Pulsover cannot do: delete or disable anything in your workspace, or make a delivered bundle unreadable. Bundles already delivered stay readable and usable by that install.
Rules reach an install only as a Rule Set Bundle:
ruleset.json plus every SQL and LLM template of one Rule
Set version. No binary embeds a rule template (the release workflow
scans every archive for them). Each bundle is:
bundle key, or a free bundle not signed with a
free key.The free bundle comes from the registration service, which takes no
Tier input, signs with the free key only, and checks its
templates against a manifest signed by the bundle key, so
it cannot introduce SQL that Pulsover did not approve. Paid bundles and
Licences are produced only by a human-approved promotion workflow.