Skip to main content
View Markdown ↗

Copy this page

Select and copy the Markdown below, then paste it into your LLM.

On this page

Portal API reference

The management portal's API is an open specification, so that the offline portal and the TestifySec platform can serve the same contract. Paths are under /api/v1. The tenant comes from the deployment or the credential, never from the path. JSON request bodies refuse unknown fields. Errors are RFC 9457 application/problem+json documents whose error member holds a stable code.

Every route except discovery and the device routes requires a client certificate that the portal verifies against the enclave CA. The certificate subject identifies the user, and the role (admin, approver or auditor) comes from the portal's user directory.

The portal is on main. Operations marked "specified, not built" are part of the contract and have no implementation yet.

Generated from testifysec/portal/api/openapi.yaml: Badger management portal API, version 0.6.0, OpenAPI 3.1.0.

MethodPathStatusSummary
GET/api/v1/profilesimplementedLatest signed version of every profile (admin, approver, auditor)
GET/api/v1/profiles/{profileId}/versionsimplementedEvery version of a profile, newest first, without envelopes (admin, approver, auditor)
POST/api/v1/profiles/{profileId}/versionsimplementedSign the next version (admin). The server assigns tenant and sequence.
GET/api/v1/profiles/{profileId}/trustimplementedBuild-provisioned admission trust input for this profile (admin, auditor)
GET/api/v1/profiles/{profileId}/versions/{sequence}implementedOne version, without its envelope (admin, approver, auditor)
GET/api/v1/profiles/{profileId}/versions/{sequence}/envelopeimplementedThe DSSE envelope exactly as signed (admin, approver, auditor)
GET/api/v1/deployments/{deploymentId}/assignmentimplementedThe version a deployment (device group) runs (admin, approver, auditor)
PUT/api/v1/deployments/{deploymentId}/assignmentimplementedPoint a deployment at a signed version of its profile (admin)
GET/.well-known/badger-portalimplementedDiscovery; public, names no tenant, deployment or key
GET/api/v1/usersimplementedThe user directory (admin, approver, auditor)
POST/api/v1/usersimplementedProvision an identity the enclave PKI or IdP issued (admin). Pending, no role, until an approver activates it. Inviting a pending user with no open activation request issues one; otherwise 409.
POST/api/v1/users/{userId}/drop-roleimplementedRemove an active user's role at once (admin); body {}
PUT/api/v1/users/{userId}/deployments/{deploymentId}implementedAdd an active user to a deployment (admin); body {}
DELETE/api/v1/users/{userId}/deployments/{deploymentId}implementedRemove a membership (admin); body {}
POST/api/v1/users/{userId}/offboardimplementedOffboard (admin, not self); final. Clears role and memberships and drops pending requests by or about the user; body {}
GET/api/v1/role-requestsimplementedThe approver queue, pending requests only (admin, approver, auditor)
POST/api/v1/users/{userId}/role-requestsimplementedRequest a role for an active user (admin); nothing changes until an approver decides
POST/api/v1/role-requests/{requestId}/approveimplementedApprove (approver who is neither the requester nor the user)
POST/api/v1/role-requests/{requestId}/rejectimplementedReject (same rule as approve)
GET/api/v1/device/noncespecified, not builtOne-use nonce for a device-key proof
POST/api/v1/device/profilespecified, not builtA workstation pulls its signed profile, its deployment's activation record and any pending reset

GET /api/v1/profiles

Latest signed version of every profile (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

Response 200: Versions, without envelopes

application/json:

FieldTypeRequiredDescription
itemsarray of Versionyes

Response default: Error

application/problem+json: Problem

GET /api/v1/profiles/{profileId}/versions

Every version of a profile, newest first, without envelopes (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
profileIdpathIdentifieryes

Response 200: Versions

application/json:

FieldTypeRequiredDescription
itemsarray of Versionyes

Response default: Error

application/problem+json: Problem

POST /api/v1/profiles/{profileId}/versions

Sign the next version (admin). The server assigns tenant and sequence.

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
profileIdpathIdentifieryes

Request body:

application/json:

FieldTypeRequiredDescription
deploymentIdIdentifieryes
notBeforeInstantyes
expiresAtInstantyes

Response 201: Signed and stored

application/json: Version

Response default: Error

application/problem+json: Problem

GET /api/v1/profiles/{profileId}/trust

Build-provisioned admission trust input for this profile (admin, auditor)

Exactly the schema testifysec/managed/README.md accepts; minimumSequence is the latest sequence.

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
profileIdpathIdentifieryes

Response 200: Trust input

application/json:

FieldTypeRequiredDescription
schemaVersion1yes
publicKeysarray of string (at least 1, at most 16)yes
thresholdinteger (minimum 1)yes
tenantIdIdentifieryes
deploymentIdIdentifieryes
profileIdIdentifieryes
minimumSequenceSequenceyes

Response default: Error

application/problem+json: Problem

GET /api/v1/profiles/{profileId}/versions/{sequence}

One version, without its envelope (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
profileIdpathIdentifieryes
sequencepathstring (pattern ^[1-9][0-9]{0,15}$)yes

Response 200: Version

application/json: Version

Response default: Error

application/problem+json: Problem

GET /api/v1/profiles/{profileId}/versions/{sequence}/envelope

The DSSE envelope exactly as signed (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
profileIdpathIdentifieryes
sequencepathstring (pattern ^[1-9][0-9]{0,15}$)yes

Response 200: Envelope bytes; sha256 equals the version's envelopeSha256

application/vnd.dsse.envelope.v1+json:

FieldTypeRequiredDescription

Response default: Error

application/problem+json: Problem

GET /api/v1/deployments/{deploymentId}/assignment

The version a deployment (device group) runs (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
deploymentIdpathIdentifieryes

Response 200: Assignment

application/json: Assignment

Response default: Error

application/problem+json: Problem

PUT /api/v1/deployments/{deploymentId}/assignment

Point a deployment at a signed version of its profile (admin)

Forward only. An older sequence, or a different profile once one is assigned, is 409 rollback; roll back by signing a new version.

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
deploymentIdpathIdentifieryes

Request body:

application/json:

FieldTypeRequiredDescription
profileIdIdentifieryes
sequenceSequenceyes

Response 200: Assignment

application/json: Assignment

Response default: Error

application/problem+json: Problem

GET /.well-known/badger-portal

Discovery; public, names no tenant, deployment or key

Status: implemented. Authentication: none.

Response 200: Discovery document

application/json:

FieldTypeRequiredDescription
specVersionstringyes
apiBasestringyes
profilePayloadTypestringyes
authenticationarray of mutualTLSyes

GET /api/v1/users

The user directory (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

Response 200: Users

application/json:

FieldTypeRequiredDescription
itemsarray of Useryes

Response default: Error

application/problem+json: Problem

POST /api/v1/users

Provision an identity the enclave PKI or IdP issued (admin). Pending, no role, until an approver activates it. Inviting a pending user with no open activation request issues one; otherwise 409.

Status: implemented. Authentication: client certificate (mutual TLS).

Request body:

application/json:

FieldTypeRequiredDescription
kindx509yes
subjectstringyesCertificate subject DN

Response 201: The pending user and its activation request

application/json:

FieldTypeRequiredDescription
userUseryes
activationRoleRequestyes

Response default: Error

application/problem+json: Problem

POST /api/v1/users/{userId}/drop-role

Remove an active user's role at once (admin); body {}

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
userIdpathDigestyes

Response 200: User

application/json: User

Response default: Error

application/problem+json: Problem

PUT /api/v1/users/{userId}/deployments/{deploymentId}

Add an active user to a deployment (admin); body {}

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
userIdpathDigestyes
deploymentIdpathIdentifieryes

Response 200: User

application/json: User

Response default: Error

application/problem+json: Problem

DELETE /api/v1/users/{userId}/deployments/{deploymentId}

Remove a membership (admin); body {}

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
userIdpathDigestyes
deploymentIdpathIdentifieryes

Response 200: User

application/json: User

Response default: Error

application/problem+json: Problem

POST /api/v1/users/{userId}/offboard

Offboard (admin, not self); final. Clears role and memberships and drops pending requests by or about the user; body {}

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
userIdpathDigestyes

Response 200: User

application/json: User

Response default: Error

application/problem+json: Problem

GET /api/v1/role-requests

The approver queue, pending requests only (admin, approver, auditor)

Status: implemented. Authentication: client certificate (mutual TLS).

Response 200: Pending requests

application/json:

FieldTypeRequiredDescription
itemsarray of RoleRequestyes

Response default: Error

application/problem+json: Problem

POST /api/v1/users/{userId}/role-requests

Request a role for an active user (admin); nothing changes until an approver decides

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
userIdpathDigestyes

Request body:

application/json:

FieldTypeRequiredDescription
roleadmin, approver, auditoryes

Response 201: Request

application/json: RoleRequest

Response default: Error

application/problem+json: Problem

POST /api/v1/role-requests/{requestId}/approve

Approve (approver who is neither the requester nor the user)

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
requestIdpathstring (pattern ^[0-9a-f]{32}$)yes

Response 200: Request

application/json: RoleRequest

Response default: Error

application/problem+json: Problem

POST /api/v1/role-requests/{requestId}/reject

Reject (same rule as approve)

Status: implemented. Authentication: client certificate (mutual TLS).

ParameterInTypeRequired
requestIdpathstring (pattern ^[0-9a-f]{32}$)yes

Response 200: Request

application/json: RoleRequest

Response default: Error

application/problem+json: Problem

GET /api/v1/device/nonce

One-use nonce for a device-key proof

Status: specified, not built. Authentication: none.

Response 200: Nonce, valid for 60 seconds

application/json:

FieldTypeRequiredDescription
noncestringyes

POST /api/v1/device/profile

A workstation pulls its signed profile, its deployment's activation record and any pending reset

The device proves possession of its cilock-enrolled device key (TPM or Secure Enclave custody): proof is a compact ES256 JWS by that key over the nonce, the key thumbprint and this portal's audience. Returns both documents exactly as signed for the device's deployment. 403 when unknown or revoked. The portal never pushes.

Status: specified, not built. Authentication: none.

Request body:

application/json:

FieldTypeRequiredDescription
noncestringyes
proofstringyes

Response 200: The current pair

application/json:

FieldTypeRequiredDescription
envelopeobjectyesProfile DSSE envelope
activationobjectyesActivation record DSSE envelope
resetobjectnoPending device-bound high-water reset record (DSSE), present only when one awaits this device

Response default: Error

application/problem+json: Problem

Schemas

User

FieldTypeRequiredDescription
idDigestyes
kindx509yes
subjectstringyes
role``, admin, approver, auditoryes
statuspending, active, offboardedyes
createdAtstring (date-time)yes
createdBystringyes
deploymentsarray of Identifierno

RoleRequest

FieldTypeRequiredDescription
idstringyes
kindactivate, grantyes
userIdDigestyes
role``, admin, approver, auditoryes
requestedBystringyes
requesterIdDigestyes
requestedAtstring (date-time)yes
statuspending, approved, rejected, droppedyes
decidedBystringno
decidedAtstring (date-time)no

Assignment

FieldTypeRequiredDescription
deploymentIdIdentifieryes
profileIdIdentifieryes
sequenceSequenceyes
payloadSha256Digestyes
assignedAtstring (date-time)yes
assignedBystringyes

Identifier

string (pattern ^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$)

Instant

string (pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$)

Sequence

integer (minimum 1, maximum 9007199254740991)

Digest

string (pattern ^[0-9a-f]{64}$)

Version

FieldTypeRequiredDescription
profileIdIdentifieryes
tenantIdIdentifieryes
deploymentIdIdentifieryes
sequenceSequenceyes
notBeforeInstantyes
expiresAtInstantyes
payloadSha256Digestyes
envelopeSha256Digestyes
signerKeyIdsarray of Digestyes
createdAtstring (date-time)yes
createdBystringyesAuthenticated principal (certificate subject DN or OIDC subject)

Problem

RFC 9457 problem document; "error" repeats the stable code.

FieldTypeRequiredDescription
typestringyes
titlestringyes
statusintegeryes
detailstringno
errorunauthenticated, forbidden, cross-origin, invalid-request, invalid-profile, sequence-conflict, rollback, not-found, store, issue-failed, assign-failed, conflict, invalid-state, users-failedyes

Reference generated from the product documentation. Match commands and support details to your installed release.