Identity and access

Jnu never asks for a database password. Every query is signed by an identity, the service resolves that identity to the account it acts for, and a per-table security policy decides which rows and columns that account may see or change. This page explains the three pieces: identities and proxy keys, the ownership rules, and how to make a key that can do exactly one thing.

Who signs the query

jnu.connect(service, keystore) signs every query with keystore. Without the second argument it waits for a dcp/identity session and uses that, which is how browser pages and the <jnu-record-set> element work.

The signing address is usually a proxy key: an API key created in the Portal, or a session key issued by identity.login(). The pxAuth service maps the key’s address (proxyAddress) to the account it acts for (authAddress), and the policy is evaluated for the account. A job deployed with an API key is owned by the account, not the key, so any other key of the same account that carries the right operations can see it. A plain private key that isn’t registered as a proxy acts for itself.

Ownership

Each policy names an owner column, directly or through another table:

  • Direct: jobs.owner, computeGroups.owner, worker.owner, credsList.owner, and the owner column of every Portal table. You see rows whose owner is your account.

  • Via a job: jobPerfData, jobFinData, activeSlices, jobResults, jobData, jobArguments, workFunctions, workRejectHistory, computeGroupsJobs_byJob. You see rows whose job you own.

  • Via a Compute Group: computeGroupJobs, computeGroupAccountingData, computeGroupWorkerOrigins, computeGroupJobPeriodStats, computeGroupWorkerPeriodStats. You see rows for groups you own.

  • World: jobs_public and computeGroups_public return a few public columns to any identity.

The policy also fixes which columns a change may touch. For jobs that’s name, description and link only; as of 2026-10-03 the slice price, status and everything else are read-only through Jnu, so changing the price of a running job means cancelling and redeploying. The per-table details are on the scheduler, portal and proxy key pages.

A query you’re not allowed to make fails with Invalid operation <service>.jnu.<table>.query. A query you’re allowed to make that would return rows belonging to someone else returns nothing.

Operations a key needs

Every Jnu call is authorized against one operation key of the form <service>.jnu.<table>.<action>, where the action is query, change, delete, add, add.simple or add.changeMiss. Parent keys grant their children: scheduler.jnu.jobs grants all actions on jobs, scheduler.jnu grants every table, and $login grants everything.

To do this

The key needs

Read your jobs and their progress

scheduler.jnu.jobs.query, scheduler.jnu.jobPerfData.query, scheduler.jnu.jobResults.query, scheduler.jnu.activeSlices.query

Read everything about your jobs

add jobFinData, workRejectHistory, jobData, jobArguments, workFunctions, computeGroupsJobs_byJob, each with .query

Rename a job or change its description or link

scheduler.jnu.jobs.change

Point slice inputs or results to new storage

scheduler.jnu.jobData.change, scheduler.jnu.jobResults.change

Administer a Compute Group

scheduler.jnu.computeGroups.query and .change, plus .query on the computeGroup* tables

Manage your workers

scheduler.jnu.worker, scheduler.jnu.workerRunInfo, scheduler.jnu.workerSnapshot.query, and the config tables

Read your Portal profile and preferences

portal.jnu.user.query, portal.jnu.userPreferences.query

The job levers that aren’t Jnu calls need their own operations: job.close to pause and resume, job.cancel, job.computeGroup.add to add a running job to a group, job.results.fetch to download results, and job.exec to deploy. A key with job.exec is automatically allowed the other job.* operations on the jobs it deployed.

Making a key in the Portal

The Keys page of the Portal creates keys with a purpose, which is a preset bundle of operations:

Purpose

Operations

Good for

job-creation

job.exec

Deploying from scripts. Can’t read the database.

job-management

job.cancel, job.close, job.results

Pausing, cancelling and fetching results. Can’t read the database.

jnu-access

scheduler.jnu, portal.jnu

Read-only dashboards and reports: every table, no job levers.

wallet-access

portal.wallet

Wallet operations. Handle with care.

universal

job, scheduler.jnu, portal.jnu

Everything above. Use it for development, not for deployment.

Within a purpose, each operation can be narrowed before the key is created:

  • Expiry and uses: every row has an expiry date, and an operation can be limited to a number of uses.

  • A job: job operations can be tied to one job (related becomes job-<opaqueId>).

  • A where clause: jnu operations can be tied to rows matching a JSON prototype. The Portal shows an editor for it and validates the columns against the table. For example, scheduler.jnu.jobs.query with {"status":"running"} lets the key see running jobs only, and scheduler.jnu.jobResults.query with {"jobId": 389798} lets it read one job’s results and nothing else. The clause is merged into every query the key makes, so it can’t be bypassed from the client.

A key built this way is what to hand to a third-party service, a CI pipeline or a public dashboard: it can read exactly the rows it’s meant to and nothing else, and deleting its rows from proxyAuth revokes it.

Note

Keys are passphrase-protected keystore files when downloaded. In code, identity.set('<private key>') or new wallet.Keystore(json, passphrase) turns one into an identity. Treat the private key as the credential: anyone holding it can do whatever the key’s operations allow until it expires or is revoked.