This page summarises every grant pulsobot-installer
makes. The full table, one row per grant, is generated from the
installer's permission plan
(cmd/installer/internal/deploy/permissions.go) into docs/deployment/permissions.md. A test
(TestPermissionsDocMatchesThePlan) fails the build when the
two drift, so that page is the source of truth. This page does not
repeat it row by row.
| Identity | Created by | Exists in |
|---|---|---|
| Installing identity | You. The user or service principal that runs the installer. The
product's jobs run as this identity (no run_as
override) |
Every install |
| API app service principal | Databricks, when the installer deploys the API App | Every install |
| Test Agent service principal | The installer, with account-level OAuth | --prepare-optimize or upgrade only |
| Deployment Agent service principal | The installer, with account-level OAuth | --prepare-optimize or upgrade only |
The free Diagnose Tier is read-only on your estate: it never writes to your data, jobs, clusters or identities. It writes only to objects the product creates for itself: its own schema, volumes and secret scope.
Read on your objects:
USE_CATALOG on system,
USE_SCHEMA on system.compute,
system.billing, system.lakeflow: extraction
reads System Tables.CAN_USE on the SQL warehouse you choose (API App).Write, only on the product's own objects:
<catalog>.<schema>: USE_SCHEMA,
SELECT, MODIFY, CREATE_TABLE,
CREATE_FUNCTION, for the installing identity and for
account users (see exceptions below).binaries, staging,
remediation_artifacts): read and write, to upload binaries
and cache the Rule Set Bundle.WRITE for the installing
identity, READ for the API App (see exceptions below).CAN_USE on the product's own App and
CAN_VIEW on its own jobs for workspace users.No grant the Diagnose Tier holds on one of your objects is
write-level. Two tests pin this:
TestPermissionPlan_DiagnoseIsReadOnlyOnTheCustomerEstate
and
TestPermissionPlan_DiagnoseWritesAreExactlyTheseOnes.
An Optimize Licence adds no permission. It opens gates in code only: paid rules, LLM analysis, Monitor, more Accounts and, on a prepared install, remediation. See Licence model.
--prepare-optimize or upgradeRemediation needs agents that act on your jobs. They are installed
only when you ask:
pulsobot-installer install --prepare-optimize, or later
pulsobot-installer upgrade. Setting
FF_REMEDIATION=false skips all of this even with
--prepare-optimize.
| Grant | Why |
|---|---|
| Two account-level service principals created: Test Agent, Deployment Agent | Each agent has its own identity |
Deployment Agent: workspace ADMIN and
CAN_MANAGE on every job |
Deploys the remediated job definitions it was approved to deploy (ADR-0019) |
Test Agent: USE_CATALOG, USE_SCHEMA,
SELECT on the catalogs you list in
PULSOBOT_REMEDIATED_CATALOGS, plus CREATE on
its own sandbox schema |
Replays a workload in a sandbox and compares outputs |
Installing identity: SELECT on the same catalogs, and
read/write on the product's Lakebase remediation
schema |
Verification Agent compares outputs; agents record Remediation Orders |
CAN_QUERY on the Foundation Model serving endpoints in
use |
LLM code analysis, an Optimize-only stage; a Diagnose install never gets this grant |
Agent identities: READ on the product secret scope |
Agents read their own OAuth credential |
The Remediation, Test and Deployment Agents stay
dormant until a valid Optimize Licence is present: each
run logs dormant and exits 0 without taking work. The
Verification and Cleanup Agents never check the Licence: they only
finish work already in flight (see Licence
model). Every change to a job still goes through a Remediation Order
that a human approves.
Account-admin credentials. Creating the two service
principals needs account-level OAuth
(DATABRICKS_ACCOUNT_CLIENT_ID /
DATABRICKS_ACCOUNT_CLIENT_SECRET, or a profile). The
installer passes them only to the account CLI calls of that run. They
are never written to the secret scope, the install state file
(~/.pulsobot/…, configuration only) or a bundle variable
(TestAccountAdminCredentialsAreNeverPersisted,
TestSaveConfigToState_NeverStoresCredentials). The scope
keeps only the agents' own service-principal credentials, which the
installer created.
WRITE on the product secret scope for the
installing identity. The rules job runs as this identity and
installs a Licence it picked up from the delivery store, so a renewal
needs no human step. WRITE can put and delete secrets in
that scope only. It cannot change the scope's ACLs or delete the scope
(that is MANAGE, which the product does not hold).account users, read
and write. account users get the same grants as
the installing identity on the product's own schema:
USE_CATALOG, USE_SCHEMA, SELECT,
MODIFY, CREATE_TABLE,
CREATE_FUNCTION. The API App's service principal writes its
Account and settings tables through this grant. It covers only the
product's own schema, never one of your objects. Narrowing it to
read-only for people is planned as a follow-up.--prepare-optimize or
upgrade, and the agent deploys only approved Remediation
Orders.All in the product's own secret scope (scope name = product ID):
| Secret | Purpose |
|---|---|
licence |
The Licence file (public, signed; not a secret, stored here for access control) |
install_key |
The private half of the Install Key, which decrypts Rule Set Bundles and Licences delivered to this install. It never leaves the workspace |
| Agent OAuth credentials | Prepared installs only: the Test and Deployment Agents' own service principals |
| Per-Account credentials | For each Account you register, the credentials you provide to read it (see Account operations in the deployment guide) |
The product holds no Pulsover credential and no credential Pulsover can use.