# Omnibus app-layer services

Omnibus’s own services, separate from the core TrustGraph API. Reach out to discuss building on them.



**Note**
**Omnibus app layer.** These are Omnibus’s own services, built on top of TrustGraph. They are not part of the core TrustGraph API. If you want to build on them, [reach out](mailto:hello@rebellion.systems?subject=TrustGraph%20integration).

Omnibus is [an app built on TrustGraph](/ecosystem/omnibus). This page collects its existing encryption-key and profile contracts, separately from core identity, device approval, vouches and reachability. Discuss access and configuration with the team before integrating.

## Feed encryption-key directory

Omnibus uses device encryption-key advertisements for encrypted delivery. Core device approval and quarantine are described in [device authority](/api/devices).

`POST /v1/devices/log` uses signed read `device-log-read` over `{graphNodeId, afterSequence?, limit?}`. The `keys` response field contains at most the current and previous encryption-key advertisement per device. Core authority records and signing keys are described in the linked device reference. Parsing a directory does not verify its signatures or continuity; use the SDK verification helpers with retained trusted pins.

### Advertise an encryption key

`POST /v1/devices/key/advertise` takes `{action, signature}`. The signed `device-key-advertise` action contains `graphKeyId`, `ad`, `adSignature`, `nonce` and `signedAt`. Sign the advertisement with `v: "omnibus-feed-key-v1"`, then sign the outer action in the normal action domain. Signatures are canonical base64, low-S P-256 DER.

| Advertisement field | Rule |
| --- | --- |
| `graphNodeId`, `epoch`, `deviceGraphKeyId` | Approved device in the current node epoch |
| `keySequence` | Increasing positive integer |
| `encryptionPublicKey` | Canonical base64 X25519 public key, 32 bytes |
| `encryptionKeyId` | SHA-256 of the protocol’s length-framed domain and public key |
| `validFrom`, `validUntil` | UTC times exactly eight days apart |
| `issuedAt` | UTC timestamp |

Use the SDK helpers for key IDs and record signatures. Success returns `{adHash, keySequence}`. Equal sequence and equal unsigned hash is idempotent; conflicting or lower sequence returns `FEED_KEY_CONFLICT` (409). The daily rolling limit is two advertisements per device. Responses use `Cache-Control: no-store`.

Common errors include `FEED_FORBIDDEN` (403), `FEED_UNAUTHORIZED` (401), `FEED_NONCE_REPLAY` (409), `FEED_RATE_LIMITED` (429), `FEED_SERVER_UNAVAILABLE` (503) and `DEVICE_LOG_NOT_APPROVED` (403).

## Profile wrap secret

Omnibus’s profile vault uses an owner-authorized wrap-secret read. This service does not upload a display name or a profile. Client applications are responsible for local encryption, key lifetime, sign-out cleanup and backup behavior.

### Capability and authorization

Read `GET /readyz` and check `profileVault: {enabled: true, wrapSecretFormat: "profile-wrap-secret-v1"}`. A missing capability on an older server means unsupported.

Send `POST /v1/profile/wrap-secret/read` with `{graphNodeId, authorization}`. Use the signed-read envelope to sign operation `read-profile-wrap-secret` over the exact query `{graphNodeId}`. The signing graph key must belong to the node and, where device authority exists, be approved. Content-signing, expired, revoked and quarantined keys cannot authorize this read; bearer credentials alone do not authorize it. Every retry needs fresh authorization and a nonce.

### Response

```json role="response"
{
  "graphNodeId": "<owner-node-id>",
  "wrapSecret": "<canonical-32-byte-base64url-secret>",
  "format": "profile-wrap-secret-v1"
}
```

Validate response ownership and format. `wrapSecret` is 32 bytes encoded as 43 canonical unpadded base64url characters. Honor `Cache-Control: no-store`.


**Never**
Never log or persist the wrapping contribution, or retain it across sign-out. Use it only in memory as a contribution to a locally derived key, not directly as the encryption key.


**Does not establish**
The wrapping contribution is readable by the service. The service does not enforce a client’s encryption, sign-out cleanup or backup policy.

### SDK helpers

`graph.profileVaultCapabilities()` reads readiness without bearer credentials and returns `null` for an absent or explicitly disabled capability. Malformed capabilities, HTTP errors and transport failures remain errors. `graph.readProfileWrapSecret({graphNodeId, authorization})` sends the signed request without an implicit capability probe. The caller supplies authorization, and custom HTTP adapters must honor `no-store`.

## Nearby discovery

Nearby uses mutual relationships and each participant’s signed audience to decide eligibility. It is not a precise-location directory. This summary describes an Omnibus service; use core [reachability](/api/query) for a TrustGraph connection check.

## Other app experiences

- **Feeds and posts:** encrypted sharing through Omnibus’s Feed experience.
- **Files:** encrypted attachments managed by the app layer.
- **Audience policy:** the app layer controls who can receive shared content.
- **Messaging:** app conversations, separate from [portable signed messages](/build/signed-messages) composed from core primitives.

Availability depends on the app release and service configuration. To discuss an integration, [reach out](mailto:hello@rebellion.systems?subject=TrustGraph%20integration).
