Pulsobot security pack

Permissions per tier

Every grant pulsobot-installer makes, per tier (ADR 0046, #759). The tables are generated from the permission plan in cmd/installer/internal/deploy/permissions.go; a test fails when they drift. The security pack (#764) builds on this page.

To change a grant, change the plan, then regenerate:

go test ./cmd/installer/internal/deploy -run PermissionsDoc -update-permissions-doc

How to read it

FF_REMEDIATION=false skips the second table even with --prepare-optimize.

The one deliberate write on the product's secret scope

The installing identity, which the jobs run as, holds WRITE on the product secret scope. The rules job needs it to install a licence it picked up from the delivery store (#756), so the API and the jobs see the new licence at their next refresh, with no human step. WRITE cannot change the scope's ACLs or delete the scope; MANAGE can, and the product does not hold it.

Known wide grant

The product schema grants (USE_CATALOG … CREATE_FUNCTION on <catalog>.<schema>) also go to account users, so human users can read and write the product's tables. They cover only the product's own schema, never a customer object.

They are not narrowed to read-only because a product flow needs them: the API's service principal writes its Delta tables (Accounts, account and cloud settings, instance discounts) through account users — it has no schema grant of its own (GrantAppVolumeAccess gives it SELECT on five tables only). Narrowing account users to USE_CATALOG/USE_SCHEMA/SELECT first needs explicit write grants to the app's service principal (follow-up).

Credentials the product never keeps

The account-admin credentials used by --prepare-optimize or upgrade (DATABRICKS_ACCOUNT_CLIENT_ID/_SECRET, or a profile) are passed only to the account CLI calls of that run. They are never written to the secret scope, the install state file (~/.pulsobot/…, config only) or a bundle variable (TestAccountAdminCredentialsAreNeverPersisted, TestSaveConfigToState_NeverStoresCredentials). The scope holds the agents' own service-principal credentials, which the installer creates.

Diagnose Tier (every install)

Principal Object Privilege Owner Applied by Why
installing identity (the jobs' run_as) catalog system USE_CATALOG customer GrantPermissions extraction reads system tables
installing identity (the jobs' run_as) schema system.compute USE_SCHEMA customer GrantPermissions extraction reads system tables
installing identity (the jobs' run_as) schema system.billing USE_SCHEMA customer GrantPermissions extraction reads system tables
installing identity (the jobs' run_as) schema system.lakeflow USE_SCHEMA customer GrantPermissions extraction reads system tables
installing identity (the jobs' run_as) + account users catalog <catalog> USE_CATALOG product GrantPermissions the jobs and the API read and write the product's own Delta tables; the API's service principal has no grant of its own for its Delta writes (accounts, settings) and relies on this one, so humans can read and write the product's schema too
installing identity (the jobs' run_as) + account users schema <catalog>.<schema> USE_SCHEMA product GrantPermissions the jobs and the API read and write the product's own Delta tables; the API's service principal has no grant of its own for its Delta writes (accounts, settings) and relies on this one, so humans can read and write the product's schema too
installing identity (the jobs' run_as) + account users schema <catalog>.<schema> SELECT product GrantPermissions the jobs and the API read and write the product's own Delta tables; the API's service principal has no grant of its own for its Delta writes (accounts, settings) and relies on this one, so humans can read and write the product's schema too
installing identity (the jobs' run_as) + account users schema <catalog>.<schema> MODIFY product GrantPermissions the jobs and the API read and write the product's own Delta tables; the API's service principal has no grant of its own for its Delta writes (accounts, settings) and relies on this one, so humans can read and write the product's schema too
installing identity (the jobs' run_as) + account users schema <catalog>.<schema> CREATE_TABLE product GrantPermissions the jobs and the API read and write the product's own Delta tables; the API's service principal has no grant of its own for its Delta writes (accounts, settings) and relies on this one, so humans can read and write the product's schema too
installing identity (the jobs' run_as) + account users schema <catalog>.<schema> CREATE_FUNCTION product GrantPermissions the jobs and the API read and write the product's own Delta tables; the API's service principal has no grant of its own for its Delta writes (accounts, settings) and relies on this one, so humans can read and write the product's schema too
installing identity (the jobs' run_as) secret scope <scope> WRITE product install.go Step 6a (ambientScopePermission) the one deliberate write outside the Delta schema: the rules job installs a picked-up licence (#756); WRITE cannot change ACLs or delete the scope
API app service principal secret scope <scope> READ product install.go Step 9b the API reads its licence and settings
installing identity (the jobs' run_as) volumes <catalog>.<schema>.* READ_VOLUME product GrantVolumeReadWriteToCurrentPrincipal upload and run the product binaries
installing identity (the jobs' run_as) volumes <catalog>.<schema>.* WRITE_VOLUME product GrantVolumeReadWriteToCurrentPrincipal upload binaries, cache the Rule Set Bundle
API app service principal catalog <catalog> USE_CATALOG product GrantAppVolumeAccess the API reads the product's own Delta tables
API app service principal schema <catalog>.<schema> USE_SCHEMA product GrantAppVolumeAccess the API reads the product's own Delta tables
API app service principal tables <catalog>.<schema>.{silver_llm_analysis, raw_workload_code, workload_code_version, code_extraction_runs, gold_workspaces} SELECT product GrantAppVolumeAccess table-level, not schema-wide: raw ingestion tables carry unredacted secrets
API app service principal volumes binaries, staging, remediation_artifacts READ_VOLUME product GrantAppVolumeAccess the app downloads its binary and reads the Rule Set Bundle
API app service principal SQL warehouse <warehouse> CAN_USE customer api_app.yml resources the API queries Delta
workspace group users app <product>-api CAN_USE product api_app.yml permissions workspace users open the dashboard
workspace group users product jobs CAN_VIEW product resources/*_job.yml permissions users see the product's own job runs
API app service principal product jobs CAN_VIEW product GrantAppJobViewAccess /health reads the product's own job runs
account users + installing identity (the jobs' run_as) catalog <product>_lakebase USE_CATALOG product GrantGenieRemediationAccess Genie space reads the product's Lakebase catalog
account users + installing identity (the jobs' run_as) schema <product>_lakebase.remediation USE_SCHEMA product GrantGenieRemediationAccess Genie space reads the product's Lakebase catalog
account users + installing identity (the jobs' run_as) schema <product>_lakebase.remediation SELECT product GrantGenieRemediationAccess Genie space reads the product's Lakebase catalog
PULSOBOT_LAKEBASE_*_USERS (operator-chosen) Lakebase database (public, remediation) SELECT / CRUD per list product GrantLakebaseUsers only when the operator names users

Extra for --prepare-optimize / upgrade

Principal Object Privilege Owner Applied by Why
installing identity (the jobs' run_as) Foundation Model serving endpoints in use CAN_QUERY customer GrantFMEndpointPermissions (install.go Step 11) LLM code analysis (Optimize Tier, ADR 0046)
installing identity (the jobs' run_as) Lakebase schema remediation SELECT, INSERT, UPDATE, DELETE product GrantAmbientIdentityLakebaseAccess agent jobs write Remediation Orders
installing identity (the jobs' run_as) remediated catalogs (PULSOBOT_REMEDIATED_CATALOGS) USE_CATALOG, USE_SCHEMA, SELECT customer GrantVerificationAgentPermissions Verification Agent compares outputs
Test Agent service principal account service principal (created) - customer EnsureTestAgentIdentity (account-level OAuth) Test Agent's own identity
Test Agent service principal remediated catalogs (read) + its sandbox schema USE_CATALOG, USE_SCHEMA, SELECT; CREATE on sandbox customer GrantTestAgentPermissions Test Agent replays workloads in a sandbox
Deployment Agent service principal account service principal (created) - customer EnsureDeploymentAgentIdentity (account-level OAuth) Deployment Agent's own identity
Deployment Agent service principal workspace ADMIN customer GrantDeploymentAgentWorkspaceAdmin (account-level OAuth) ADR-0019: deploys remediated job definitions
Deployment Agent service principal every job CAN_MANAGE customer GrantDeploymentAgentJobsAccess ADR-0019: edits the jobs it remediates
agent jobs' run_as identities secret scope <scope> READ product install.go Step 9a agents read their own OAuth credential