owner
Billing, membership and organisation settings
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.
A person is judged on their organisation role, an API key on its scopes. The dashboard and the API call the same function.
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.
The audit repository exposes no update and no delete. Twenty-one actions, each one attributed to the actor that caused it.
Data sits in ap-southeast-1, under Singapore jurisdiction. The platform lists only the regions it actually operates.
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.
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"
}
}
]
}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.
| Role | What it grants | Scopes it may put on a key |
|---|---|---|
| owner | Billing, membership and organisation settings | readtraininferadmin |
| admin | Projects and API keys | readtraininfer |
| member | Read access, and keys limited to the read scope | read |
Billing, membership and organisation settings
Projects and API keys
Read access, and keys limited to the read scope
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.
Lists and reads across the organisation. Projects, jobs, models, usage.
Starts and cancels fine-tuning jobs, and drives the training loop.
Calls your private endpoints through the OpenAI and Anthropic compatible APIs.
Membership, projects, keys, usage and the audit log. Owner-minted only.
A key is how a service acts on your behalf, so it is issued narrow and stays recognisable for as long as it lives.
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.
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.
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 and expiry are both read on every request. Rotating a key means issuing the replacement, moving the workload, then revoking the old one.
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.
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.
| Time | Actor | Action | Target | Address |
|---|---|---|---|---|
| 09:41:22 | [email protected] | apiKey.created | key_0346qEm6 | 203.0.113.42 |
| 09:38:04 | keyLedger OCR worker | fineTuning.job_created | ftjob_9wq2Lm4c | 203.0.113.8 |
| 09:12:55 | [email protected] | member.role_changed | usr_7cKpR1 member to admin | 203.0.113.42 |
| 08:55:10 | system | training.access_changed | granted | · |
| 08:41:03 | [email protected] | auth.signed_in | · | 203.0.113.42 |
There is no update path and no delete path to reach for. Rows leave when their retention deadline passes and at no other time.
A job started by a service names that key, so an unattended action traces back to the credential and the person who issued it.
Every mint, refusal and spend on the sign-in surface is recorded, and each account can read its own from settings.
Harness combines tenant boundaries, scoped credentials, audit evidence and named data residency in the same platform layer.
One access policy
Scoped API keys
Append-only audit trail
Singapore data region
Create an organisation, mint a test key, and widen its scopes when you are ready to let it write.