Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(leases):** add an explicit owner-authenticated status action that returns only the active lease's privacy-safe configured connection and provider labels, with generation fencing and no credential or internal-id disclosure ([#11910](https://github.com/diegosouzapw/OmniRoute/pull/11910)) — thanks @KaspaPulse
33 changes: 30 additions & 3 deletions docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,15 @@ paths:
post:
tags:
- Session Leases
summary: Acquire, renew, or release an exclusive managed connection lease
summary: Acquire, inspect, renew, or release an exclusive managed connection lease
description: |
Requires an API key with `lease:exclusive` and an explicit non-empty
`allowedConnections` policy. The opaque owner is bound to the authenticated API key;
the lease owns an eligible connection, not a provider or model. Managed inference
requests present the owner and exact generation headers. Temporary foreign occupancy
returns 429 `WAITING_FOR_CAPACITY` with `Retry-After`.
returns 429 `WAITING_FOR_CAPACITY` with `Retry-After`. Acquire, renew, and release retain
their connection-free response shapes. The explicit status action is owner-, key-, and
generation-fenced and returns only privacy-safe display metadata for an active binding.
security:
- BearerAuth: []
parameters:
Expand All @@ -138,6 +140,11 @@ paths:
properties:
action: { type: string, const: acquire }
model: { type: string, minLength: 1, maxLength: 512 }
- type: object
required: [action, generation]
properties:
action: { type: string, const: status }
generation: { type: integer, minimum: 1 }
- type: object
required: [action, generation]
properties:
Expand All @@ -153,7 +160,7 @@ paths:
enum: [OWNER_EXIT, CLIENT_CANCELLED]
responses:
"200":
description: Lease lifecycle state without connection or credential disclosure
description: Lease lifecycle state, with privacy-safe connection display metadata only for status
content:
application/json:
schema:
Expand Down Expand Up @@ -8002,13 +8009,33 @@ components:
schemas:
ExclusiveConnectionLeaseLifecycle:
type: object
description: >-
Shared lease lifecycle response. The optional connection object is present only for an
explicit, successful owner-authenticated status action; acquire, renew, and release never
include connection metadata.
required: [state, generation, acquiredAt, renewedAt, expiresAt]
properties:
state: { type: string, enum: [ACTIVE, RELEASED] }
generation: { type: integer, minimum: 1 }
acquiredAt: { type: string, format: date-time }
renewedAt: { type: string, format: date-time }
expiresAt: { type: string, format: date-time }
connection:
type: object
description: >-
Privacy-safe metadata for the exact active binding. Wrong-key, wrong-owner,
stale-generation, missing, expired, released, or invalidated leases return a generic
409 without this object. No credential, internal id, owner identity, or email fallback
is serialized.
required: [displayName, provider]
properties:
displayName:
type: [string, "null"]
description: Trimmed operator-configured name, or null when no privacy-safe name exists.
provider:
type: string
minLength: 1
description: Non-sensitive provider display label, never a generated compatible-provider id.
ExclusiveConnectionLeaseCapacity:
type: object
required: [state, error, reason, retryAfter, eligibleCount, freeCount]
Expand Down
44 changes: 41 additions & 3 deletions docs/reference/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ X-OmniRoute-Lease-Owner: vlo_<43-base64url-characters>
{"action":"acquire","model":"glm/glm-4.6"}
```

Successful lifecycle responses expose timestamps, `state`, and the exact positive `generation`,
but never the selected connection or credentials. Renew and release supply the generation in the
JSON body:
Successful acquire, renew, and release responses expose timestamps, `state`, and the exact positive
`generation`, but never the selected connection or credentials. Renew and release supply the
generation in the JSON body:

```json
{ "action": "renew", "generation": 1 }
Expand All @@ -119,6 +119,44 @@ JSON body:
{ "action": "release", "generation": 1, "reason": "OWNER_EXIT" }
```

An active lease owner can explicitly request privacy-safe display metadata for its current binding:

```json
{ "action": "status", "generation": 1 }
```

```json
{
"state": "ACTIVE",
"generation": 1,
"acquiredAt": "2026-08-28T12:00:00.000Z",
"renewedAt": "2026-08-28T12:00:30.000Z",
"expiresAt": "2026-08-28T12:02:30.000Z",
"connection": {
"displayName": "Primary Codex",
"provider": "codex"
}
}
```

This opt-in status action is fenced by the opaque owner, authenticated managed API key, and exact
active generation in one database transaction. `displayName` is only the trimmed configured
connection name; it is `null` when no safe configured name exists. OmniRoute never substitutes an
email or generated account identity. The provider value is a non-sensitive display label and never
a generated compatible-provider identifier. Credentials, tokens, cookies, raw connection or API
key ids, owner hashes, fencing secrets, and internal routing data are excluded.

Wrong-key, wrong-owner, stale-generation, missing, expired, released, and invalidated lookups all
return the same `409 LEASE_FENCE_STALE` error without connection metadata. A client that received the capacity-wait response has no active binding to inspect. When routing transitions an active lease,
the same generation remains valid and status atomically returns the new binding, never the old one.
Existing clients remain unchanged because acquire, renew, release, and waiting responses retain
their previous shapes.

This server contract does not change stock OpenAI Codex `/status`. Stock Codex currently reports its
model provider and built-in authentication/account state but does not render arbitrary custom
provider account metadata; a later client integration must call this action and decide how to
display `connection.displayName`.

Every managed inference request then supplies both control headers:

```http
Expand Down
6 changes: 4 additions & 2 deletions skills/omni-inference/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ All requests require a valid Bearer token or session cookie. Obtain a token via

### POST /api/v1/session-leases

Acquire, renew, or release an exclusive managed connection lease
Acquire, inspect, renew, or release an exclusive managed connection lease

Requires an API key with `lease:exclusive` and an explicit non-empty
`allowedConnections` policy. The opaque owner is bound to the authenticated API key;
the lease owns an eligible connection, not a provider or model. Managed inference
requests present the owner and exact generation headers. Temporary foreign occupancy
returns 429 `WAITING_FOR_CAPACITY` with `Retry-After`.
returns 429 `WAITING_FOR_CAPACITY` with `Retry-After`. Acquire, renew, and release retain
their connection-free response shapes. The explicit status action is owner-, key-, and
generation-fenced and returns only privacy-safe display metadata for an active binding.


```bash
Expand Down
15 changes: 15 additions & 0 deletions src/app/api/v1/session-leases/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { isCommonChatGptWebRetirementError } from "@/shared/constants/chatgptWeb
import { enforceApiKeyPolicy } from "@/shared/utils/apiKeyPolicy";
import { CORS_HEADERS, handleCorsOptions } from "@/shared/utils/cors";
import {
getExclusiveConnectionLeaseStatus,
releaseExclusiveConnectionLease,
renewExclusiveConnectionLease,
} from "@/lib/db/exclusiveConnectionLeases";
import { getProviderDisplayName } from "@/lib/display/names";
import {
extractApiKey,
getProviderCredentialsWithQuotaPreflight,
Expand All @@ -29,6 +31,7 @@ const action = <T extends string>(name: T, shape: z.ZodRawShape) =>
const generation = z.number().int().positive().safe();
const actionSchema = z.discriminatedUnion("action", [
action("acquire", { model: z.string().trim().min(1).max(512) }),
action("status", { generation }),
action("renew", { generation }),
z.object({
action: z.literal("release"),
Expand Down Expand Up @@ -95,6 +98,18 @@ export async function POST(request: Request): Promise<Response> {
generation: parsed.data.generation,
apiKeyId: policy.apiKeyInfo.id,
};
if (parsed.data.action === "status") {
const status = getExclusiveConnectionLeaseStatus(input);
return status
? json(200, {
...lifecycle(status.lease),
connection: {
displayName: status.connectionName,
provider: getProviderDisplayName(status.provider),
},
})
: error(409, "LEASE_FENCE_STALE", "The lease generation is stale");
}
const result =
parsed.data.action === "renew"
? renewExclusiveConnectionLease(input)
Expand Down
60 changes: 60 additions & 0 deletions src/lib/db/exclusiveConnectionLeases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ type LeaseRow = {
state: ExclusiveLeaseState;
expires_at: string;
};
type LeaseStatusRow = LeaseRow & {
connection_provider: string;
connection_auth_type: string | null;
connection_name: string | null;
connection_email: string | null;
connection_display_name: string | null;
};
type LeaseSuccess = {
kind: "ACQUIRED" | "REUSED" | "TRANSITIONED";
lease: ExclusiveConnectionLease;
Expand Down Expand Up @@ -92,6 +99,21 @@ function active(column: "lease_owner_hash" | "connection_id", value: string) {
return database().prepare(`${ACTIVE_SQL}${column} = ?`).get(value) as LeaseRow | undefined;
}

function configuredConnectionName(row: LeaseStatusRow): string | null {
const name = row.connection_name?.trim();
if (!name || name.includes("@")) return null;

if (row.connection_auth_type === "oauth" || row.connection_auth_type === "access_token") {
const normalized = name.toLowerCase();
const generatedFallbacks = [row.connection_email, row.connection_display_name]
.map((value) => value?.trim().toLowerCase())
.filter((value): value is string => Boolean(value));
if (generatedFallbacks.includes(normalized)) return null;
}

return name;
}

function historical(ownerHash: string, generation: number) {
return database()
.prepare(
Expand Down Expand Up @@ -192,6 +214,44 @@ export function reconcileExpiredExclusiveConnectionLeases(now?: string): number
return immediate(() => expire(timestamp(now)));
}

export function getExclusiveConnectionLeaseStatus(input: {
leaseOwnerId: string;
generation: number;
apiKeyId: string;
now?: string;
}): {
lease: ExclusiveConnectionLease;
provider: string;
connectionName: string | null;
} | null {
const ownerHash = hashLeaseOwnerId(input.leaseOwnerId);
const now = timestamp(input.now);
return immediate(() => {
expire(now);
const row = database()
.prepare(
`SELECT leases.*, connections.provider AS connection_provider,
connections.auth_type AS connection_auth_type,
connections.name AS connection_name,
connections.email AS connection_email,
connections.display_name AS connection_display_name
FROM exclusive_connection_leases leases
INNER JOIN provider_connections connections ON connections.id = leases.connection_id
WHERE leases.lease_owner_hash = ? AND leases.api_key_id = ?
AND leases.generation = ? AND leases.state = 'ACTIVE' AND leases.expires_at > ?
LIMIT 1`
)
.get(ownerHash, input.apiKeyId, input.generation, now) as LeaseStatusRow | undefined;
return row
? {
lease: lease(row),
provider: row.connection_provider,
connectionName: configuredConnectionName(row),
}
: null;
});
}

export function acquireExclusiveConnectionLease(input: {
leaseOwnerId: string;
apiKeyId: string;
Expand Down
Loading
Loading