Harness

Every action your model takes is checked, scoped and logged.

One access policy governs every request, whether it arrives from a person or an API key. Keys carry no more authority than whoever minted them, and every change lands in a log with no delete path.

One policy, two actors

A person is judged on their organisation role, an API key on its scopes. The dashboard and the API call the same function.

Keys that cannot escalate

The scopes a key may carry are capped by the role of the member who created it. A member mints read keys and nothing else.

A log with no delete path

The audit repository exposes no update and no delete. Twenty-one actions, each one attributed to the actor that caused it.

Residency you can name

Data sits in ap-southeast-1, under Singapore jurisdiction. The platform lists only the regions it actually operates.

The check

Four gates, always in the same order

Every resolver asks one function before it touches data. The organisation is tested first, so a request for another tenant's resource is refused before the policy looks at roles at all.

  1. Requestactor · action · resource
  2. 01

    Same organisation?

    actor.orgId === resource.orgId
    refuseswrong_org
  3. 02

    Enough authority?

    userrole rank >= required
    keyscopes includes required
    refusesinsufficient_rolemissing_scope
  4. 03

    Project in range?

    a bound key sees one project
    refusesproject_mismatch
  5. Allowed{ allowed: true }

A refusal that says what was missing

Denials answer in one documented vocabulary across the API and the dashboard. When a key is turned away for its scopes, the response names the scope it needed, so the caller can fix the key with a precise requirement.

{
  "errors": [
    {
      "message": "You do not have permission to perform this action.",
      "extensions": {
        "code": "permission_error",
        "required_scope": "train"
      }
    }
  ]
}
Roles and scopes

People hold roles. Keys hold scopes.

Three roles, ranked, describe what a person may do. Four scopes describe what a key may do. The bridge between them is a ceiling: the role of the member creating a key decides the strongest scope that key can ever carry.

owner

Billing, membership and organisation settings

readtraininferadmin

admin

Projects and API keys

readtraininfer

member

Read access, and keys limited to the read scope

read

The ceiling, drawn

Each column is what a member of that role may put on a key they create. The dashed rule is the ceiling; everything above it is out of reach, which is why minting a key provides no path to climb.

member
admin
infer
train
read
admin
admin
infer
train
read
owner
admin
infer
train
read

read

Lists and reads across the organisation. Projects, jobs, models, usage.

train

Starts and cancels fine-tuning jobs, and drives the training loop.

infer

Calls your private endpoints through the OpenAI and Anthropic compatible APIs.

admin

Membership, projects, keys, usage and the audit log. Owner-minted only.

Keys

Credentials you can hand out and take back

A key is how a service acts on your behalf, so it is issued narrow and stays recognisable for as long as it lives.

Ledger OCR worker

nk_live_8x…
live
Scopes
readinfer
Project
proj_ledger_ocr
Expires
31 March 2027
Created 14 Aug 2026 by an admin

Shown once, stored as a hash

The secret appears at creation and never again. Only its SHA-256 hash is kept, so a lost key is replaced, and a copy of the database yields nothing anyone can authenticate with.

The environment is in the prefix

nk_live_ and nk_test_ tell a reviewer which is which at a glance, in a log line or a pull request. A ten-character display prefix identifies a key in a list without ever being enough to use it.

Bound to one project

A bound key sees that project's resources and refuses calls that reach across the organisation. Give a workload its own project and its own key, and the blast radius of a leak is that project.

Revocation takes effect on the next call

Revocation and expiry are both read on every request. Rotating a key means issuing the replacement, moving the workload, then revoking the old one.

What a leaked key reaches

A key bound to a project sees that project and refuses everything else, organisation-wide calls included. Give each workload its own project and its own key, and a leak is contained to the one box it was issued for.

nk_live_8x…
bound to proj_ledger_ocr
org_acme
ledger_ocrvisible
claimsrefused
payrollrefused
supportrefused
The trail

A log that counts as evidence

Twenty-one actions are recorded against the organisation they happened in, each carrying the actor, the target, the address it came from and the moment it landed. The repository that writes them exposes no update and no delete.

fineTuning.job_created

09:38:04
keyLedger OCR worker
ftjob_9wq2Lm4c · 203.0.113.8

training.access_changed

08:55:10
system
granted · ·

Append only, by construction

There is no update path and no delete path to reach for. Rows leave when their retention deadline passes and at no other time.

Keys are actors too

A job started by a service names that key, so an unattended action traces back to the credential and the person who issued it.

Sign-in activity, per address

Every mint, refusal and spend on the sign-in surface is recorded, and each account can read its own from settings.

Enterprise security

Controls that stay with every request

Harness combines tenant boundaries, scoped credentials, audit evidence and named data residency in the same platform layer.

Learn about security about /securityLearn about security
  • One access policy

  • Scoped API keys

  • Append-only audit trail

  • Singapore data region

Start with a key that can only read.

Create an organisation, mint a test key, and widen its scopes when you are ready to let it write.