@omnicross/daemon 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import * as _omnicross_core from '@omnicross/core';
2
2
  import { OutboundApiServerConfig, Logger, ProviderConfigSource, TransformerService, Transformer, ResolvedTransformerChain, ApiServerSettingsStore, PricingStore, AutomaticPricingSource, OutboundKeyDb, OutboundKeyDbRow, OutboundKeyPolicy, PricingEngine as PricingEngine$1 } from '@omnicross/core';
3
3
  import { ApiKeyPoolService } from '@omnicross/core/completion/ApiKeyPoolService';
4
4
  import { AllowanceSchedulingConfig, AccountProbeConfig, OutboundKeyDb as OutboundKeyDb$1, VoucherDb, KeySpendReader, OutboundApiServer } from '@omnicross/core/outbound-api';
5
- import { ProviderProxy } from '@omnicross/core/provider-proxy';
5
+ import { RouteLeaseManager, ProviderProxy } from '@omnicross/core/provider-proxy';
6
6
  import { UsageRecorder, PricingEngine } from '@omnicross/core/usage';
7
7
  import { SubscriptionCredentialStore, FetchLike, SubscriptionProviderRegistry, SubscriptionAccountService } from '@omnicross/subscriptions';
8
8
  import { AccountAllowanceSnapshot } from '@omnicross/contracts/account-allowance-types';
@@ -15,7 +15,7 @@ import { SubscriptionIdentityStore } from '@omnicross/core/provider-proxy/identi
15
15
  import { LoggingConfig, HealthReport } from '@omnicross/contracts/health-logging-types';
16
16
  import { SubscriptionAccountHealth } from '@omnicross/core/pipeline/SubscriptionAccountHealth';
17
17
  import { fetchUpstream } from '@omnicross/core/pipeline/upstreamFetch';
18
- import { AuditRecord, AuditConfig } from '@omnicross/contracts/audit-types';
18
+ import { AuditRecord, AuditStats, AuditConfig } from '@omnicross/contracts/audit-types';
19
19
  import { BillingDeliveryStatus, BillingConfig, BillingEvent } from '@omnicross/contracts/billing-types';
20
20
  import http from 'node:http';
21
21
  import { LLMProvider, AgentDefaultModels, GlobalModelParameters } from '@omnicross/contracts/llm-config';
@@ -579,6 +579,12 @@ declare class JsonSubscriptionCredentialStore implements SubscriptionCredentialS
579
579
  * TEST-injected `fetchImpl` is returned verbatim; otherwise the refresh routes
580
580
  * through {@link fetchUpstream} with the account's `{ providerId, accountId }`
581
581
  * ctx so the per-account/provider proxy applies. `@internal` also a test seam.
582
+ *
583
+ * `redactBodies` is REQUIRED here: this round-trip sends the refresh_token and
584
+ * receives a fresh access/refresh token pair. Carrying a `providerId` opts the
585
+ * call into the upstream trace (so a failing refresh is diagnosable), and the
586
+ * trace captures bodies verbatim — without this flag every refresh would write
587
+ * a plaintext token pair into `upstream-trace.jsonl`.
582
588
  */
583
589
  buildRefreshFetch(providerId: string, accountId?: string): FetchLike;
584
590
  /**
@@ -923,11 +929,12 @@ interface SubscriptionTokenWriter {
923
929
  * app-parity child 4, design D1).
924
930
  *
925
931
  * `start` mints a crypto-random `sessionId` and stashes the per-session PKCE
926
- * `{ providerId, codeVerifier, state }` here; `complete` does a SINGLE-USE
927
- * `take(sessionId)` (returns + deletes) and exchanges the code. The map is
932
+ * `{ providerId, codeVerifier, state }` here; `complete` `peek`s the session,
933
+ * exchanges the code, and `consume`s it ONLY once a token was minted so a
934
+ * failed exchange leaves the session retryable instead of burning it. The map is
928
935
  * NEVER serialized to the client — only the opaque `sessionId` + the public
929
936
  * `authUrl` cross the wire. Sessions are short-lived (OQ3 = 10-min TTL); a sweep
930
- * reaps abandoned sessions, and `take` re-checks the TTL so an expired-but-not-
937
+ * reaps abandoned sessions, and `peek` re-checks the TTL so an expired-but-not-
931
938
  * yet-swept session is still rejected. A daemon restart simply drops in-flight
932
939
  * logins (correct fail-safe — no partial token is ever written).
933
940
  *
@@ -963,13 +970,25 @@ declare class OAuthSessionStore {
963
970
  */
964
971
  put(session: Omit<PendingOAuthSession, 'createdAt'>): string;
965
972
  /**
966
- * SINGLE-USE consume: return + delete the session for `sessionId`, or `null`
967
- * when it is unknown, already used, or past its TTL (in which case it is
968
- * dropped). A `null` return means the completer must reject (no exchange, no
969
- * write).
973
+ * NON-DESTRUCTIVE lookup: return the session for `sessionId`, or `null` when
974
+ * it is unknown, already consumed, or past its TTL (an expired entry is
975
+ * dropped here). A `null` return means the completer must reject (no
976
+ * exchange, no write).
977
+ *
978
+ * Deliberately NOT a consume: the completer peeks, runs the token exchange,
979
+ * and only {@link consume}s once a token has actually been minted. Consuming
980
+ * up-front burned the session on EVERY failed exchange (a mistyped/expired
981
+ * pasted code, a proxy hiccup), so the user's natural retry hit
982
+ * "session is unknown, expired, or already used" and the login became
983
+ * unrecoverable without restarting the whole flow.
984
+ */
985
+ peek(sessionId: string): PendingOAuthSession | null;
986
+ /**
987
+ * SINGLE-USE burn: drop the session so the same `sessionId` can never be
988
+ * completed twice. Called ONLY after a successful token exchange.
970
989
  */
971
- take(sessionId: string): PendingOAuthSession | null;
972
- /** Drop every session past its TTL. Called on each put/take. */
990
+ consume(sessionId: string): void;
991
+ /** Drop every session past its TTL. Called on each put/peek. */
973
992
  private sweep;
974
993
  }
975
994
 
@@ -983,10 +1002,12 @@ declare class OAuthSessionStore {
983
1002
  * provider's authorize params and stashes the per-session `{ codeVerifier, state }`
984
1003
  * in the `OAuthSessionStore` keyed by a minted opaque `sessionId`, returning ONLY
985
1004
  * `{ authUrl, sessionId }` (the `authUrl` carries client_id + PKCE challenge +
986
- * state — all public). `complete` does a SINGLE-USE `take(sessionId)`, validates
987
- * state (claude's `code#state`), `exchangeCodeForTokens(...)`, persists the minted
988
- * token through the encrypted credential store (`appendProviderAccount`) + marks
989
- * it active, and responds ONLY the sanitized `SubscriptionListEntry`.
1005
+ * state — all public). `complete` `peek`s the session, validates state (claude's
1006
+ * `code#state`), `exchangeCodeForTokens(...)`, then and ONLY then — `consume`s
1007
+ * the session (single-use), persists the minted token through the encrypted
1008
+ * credential store (`appendProviderAccount`) + marks it active, and responds ONLY
1009
+ * the sanitized `SubscriptionListEntry`. A FAILED exchange leaves the session
1010
+ * intact so the user can retry within its TTL instead of being locked out by a 410.
990
1011
  *
991
1012
  * SECRET SPINE (the load-bearing invariant): the minted access/refresh token
992
1013
  * NEVER appears in any response body or log; the `codeVerifier` / session map is
@@ -1283,7 +1304,14 @@ interface ProbeRecord {
1283
1304
  /** Upstream round-trip latency (ms); absent for a local-tier record. */
1284
1305
  latencyMs?: number;
1285
1306
  /** Which tier produced this record. */
1286
- tier: 'local' | 'upstream';
1307
+ tier: 'local' | 'upstream' | 'generation';
1308
+ }
1309
+ /** Secret-free outcome returned by the manual account connection-test route. */
1310
+ interface AccountConnectionProbeOutcome {
1311
+ ok: boolean;
1312
+ marked: boolean;
1313
+ tier: ProbeRecord['tier'];
1314
+ model?: string;
1287
1315
  }
1288
1316
  /** Per-account probe history for the authed admin surface (names account ids). */
1289
1317
  interface AccountProbeHistorySnapshot {
@@ -1303,6 +1331,8 @@ interface AccountProbeHistoryReader {
1303
1331
  interface ProbeCredentialStore {
1304
1332
  getFullConfig(): Promise<AccountTokensConfig>;
1305
1333
  getAccessTokenForAccount(providerId: SubscriptionProviderId, accountId: string): Promise<string | null>;
1334
+ /** Optional serving-parity retry seam for an upstream Codex 401. */
1335
+ refreshAccountToken?(providerId: SubscriptionProviderId, accountId: string): Promise<boolean>;
1306
1336
  }
1307
1337
  /** Proxy-aware upstream fetch signature (#3 `fetchUpstream`). */
1308
1338
  type ProbeFetch = typeof fetchUpstream;
@@ -1352,10 +1382,13 @@ declare class AccountHealthProbeScheduler implements AccountProbeHistoryReader {
1352
1382
  * no upstream); else the upstream tier when a verified endpoint exists. Records
1353
1383
  * the rolling history entry either way; returns whether the tracker was MARKED.
1354
1384
  */
1355
- probeAccount(providerId: SubscriptionProviderId, accountId: string): Promise<{
1356
- ok: boolean;
1357
- marked: boolean;
1358
- }>;
1385
+ probeAccount(providerId: SubscriptionProviderId, accountId: string): Promise<AccountConnectionProbeOutcome>;
1386
+ /**
1387
+ * Manual connection test. Codex performs a real, quota-consuming generation;
1388
+ * every other provider keeps its existing cheap probe. Scheduled sweeps never
1389
+ * call this method, so they remain non-billable.
1390
+ */
1391
+ testAccountConnection(providerId: SubscriptionProviderId, accountId: string): Promise<AccountConnectionProbeOutcome>;
1359
1392
  /** Per-account rolling history for the authed admin surface (design D5). */
1360
1393
  getAllHistory(): AccountProbeHistorySnapshot[];
1361
1394
  /**
@@ -1374,6 +1407,7 @@ declare class AccountHealthProbeScheduler implements AccountProbeHistoryReader {
1374
1407
  private record;
1375
1408
  /** Read a bounded slice of the response body for the 403-ban sniff (never throws). */
1376
1409
  private readBounded;
1410
+ private runCodexGenerationAttempt;
1377
1411
  private key;
1378
1412
  private parseKey;
1379
1413
  }
@@ -1400,6 +1434,18 @@ interface AuditQuery {
1400
1434
  limit?: number;
1401
1435
  }
1402
1436
 
1437
+ /**
1438
+ * Metadata-only audit aggregation. The overview needs request/error counts, not
1439
+ * multi-gigabyte request/response bodies. A compact per-day sidecar is updated
1440
+ * with each new record; legacy files are scanned once with a bounded prefix per
1441
+ * JSONL row and then cached in the same sidecar.
1442
+ */
1443
+
1444
+ interface AuditStatsQuery {
1445
+ from?: number;
1446
+ to?: number;
1447
+ }
1448
+
1403
1449
  /**
1404
1450
  * auditQueryApi — the AUTHED `GET /admin/api/audit?keyId=&from=&to=&limit=`
1405
1451
  * handler (request-audit-log, design D6).
@@ -1419,6 +1465,8 @@ interface AuditQuery {
1419
1465
 
1420
1466
  /** The read surface the AdminServer consumes (bootstrap binds it to the store). */
1421
1467
  type AuditQueryReader = (query: AuditQuery) => AuditRecord[];
1468
+ /** Metadata-only aggregate reader used by the overview. */
1469
+ type AuditStatsReader = (query: AuditStatsQuery) => Promise<AuditStats> | AuditStats;
1422
1470
 
1423
1471
  /**
1424
1472
  * billingStatusApi — the AUTHED `GET /admin/api/billing-status` handler
@@ -1783,6 +1831,7 @@ declare class IntegrationManager {
1783
1831
  /** Injectable PATH probe (tests stub this; default scans `process.env.PATH`). */
1784
1832
  type PathProbe = (candidate: string) => string | null;
1785
1833
  /** Open a NEW terminal window running `command [extraArgs…]` with `env` injected. */
1834
+ type TerminalCleanup = () => void;
1786
1835
  type TerminalOpener = (input: {
1787
1836
  cli: string;
1788
1837
  command: string;
@@ -1790,7 +1839,8 @@ type TerminalOpener = (input: {
1790
1839
  env: Record<string, string>;
1791
1840
  cwd?: string;
1792
1841
  platform: NodeJS.Platform;
1793
- }) => void;
1842
+ onFailure?: () => void;
1843
+ }) => void | TerminalCleanup;
1794
1844
  /**
1795
1845
  * Injectable shell runner for `POST /cli/:cli/install` (tests stub this; the
1796
1846
  * default execs the install command with a bounded timeout). Returns the host's
@@ -1899,6 +1949,8 @@ interface AdminApiDeps {
1899
1949
  readonly settingsStore: JsonApiServerSettingsStore;
1900
1950
  /** The running outbound server (status + live applyConfig). */
1901
1951
  readonly outboundApiServer: OutboundApiServer;
1952
+ /** Process-local machine-managed routing leases (optional for light embedders). */
1953
+ readonly routeLeaseManager?: RouteLeaseManager;
1902
1954
  /** Subscription accounts (token-free `listAll`). */
1903
1955
  readonly subscriptionAccounts: AdminAccountsLister;
1904
1956
  /**
@@ -1914,6 +1966,12 @@ interface AdminApiDeps {
1914
1966
  ok: boolean;
1915
1967
  marked: boolean;
1916
1968
  }>;
1969
+ testAccountConnection(providerId: _omnicross_contracts_subscription_types.SubscriptionProviderId, accountId: string): Promise<{
1970
+ ok: boolean;
1971
+ marked: boolean;
1972
+ tier: 'local' | 'upstream' | 'generation';
1973
+ model?: string;
1974
+ }>;
1917
1975
  };
1918
1976
  /**
1919
1977
  * Least-authority subscription-token WRITER (design D4) — ONLY the mutation
@@ -1936,11 +1994,13 @@ interface AdminApiDeps {
1936
1994
  */
1937
1995
  readonly oauthSessions: OAuthSessionStore;
1938
1996
  /**
1939
- * Injected token-exchange `FetchLike` (oauth design D2-a) — defaults to global
1940
- * `fetch` in `bootstrap.ts`; tests inject a mock so no real token endpoint is
1941
- * hit. Mirrors how `login.ts` injects its exchange fetch.
1997
+ * Injected token-exchange `FetchLike` FACTORY (oauth design D2-a) — built per
1998
+ * provider in `bootstrap.ts` so the exchange carries a `{ providerId }` egress
1999
+ * ctx (per-provider proxy layer + upstream trace, bodies redacted); tests
2000
+ * inject a mock so no real token endpoint is hit. Mirrors how `login.ts`
2001
+ * injects its exchange fetch.
1942
2002
  */
1943
- readonly oauthExchangeFetch: FetchLike;
2003
+ readonly oauthExchangeFetch: (providerId: SubscriptionProviderId) => FetchLike;
1944
2004
  /**
1945
2005
  * NARROW append handle (oauth design D2-a) — the OAuth complete handler needs
1946
2006
  * `appendProviderAccount` (NOT on the least-authority `SubscriptionTokenWriter`).
@@ -2062,6 +2122,8 @@ interface AdminServerDeps extends AdminApiDeps {
2062
2122
  * unauthenticated, NEVER on `/health`.
2063
2123
  */
2064
2124
  auditReader?: AuditQueryReader;
2125
+ /** Metadata-only audit aggregate used by the overview error-rate metric. */
2126
+ auditStatsReader?: AuditStatsReader;
2065
2127
  /**
2066
2128
  * OPTIONAL billing delivery-status reader (billing-event-stream, design D5).
2067
2129
  * When wired (bootstrap → the ledger dir), the AUTHED `GET /admin/api/billing-status`
@@ -2106,7 +2168,16 @@ declare class AdminServer {
2106
2168
 
2107
2169
  declare class JsonOutboundKeyDb implements OutboundKeyDb {
2108
2170
  private readonly keysPath;
2109
- constructor(keysPath: string);
2171
+ private readonly secretBox?;
2172
+ /**
2173
+ * @param secretBox OPTIONAL reversible-secret codec. When present, a created
2174
+ * key's plaintext is persisted as a `keySecret` `enc:` envelope (enabling the
2175
+ * operator "view key" affordance via `outboundApiKeysReveal`). When absent the
2176
+ * store stays hash-only (byte-identical to the legacy behavior) and reveal
2177
+ * always returns `null`. Existing 1-arg call sites (tests, lightweight
2178
+ * embedders) keep working.
2179
+ */
2180
+ constructor(keysPath: string, secretBox?: SecretBox | undefined);
2110
2181
  outboundApiKeysList(): Promise<OutboundKeyDbRow[]>;
2111
2182
  outboundApiKeysGetByHash(hash: string): Promise<OutboundKeyDbRow | null>;
2112
2183
  outboundApiKeysCreate(input: {
@@ -2118,7 +2189,10 @@ declare class JsonOutboundKeyDb implements OutboundKeyDb {
2118
2189
  kind?: 'client' | 'integration';
2119
2190
  allowedEndpoints?: _omnicross_core.OutboundEndpoint[];
2120
2191
  loopbackOnly?: boolean;
2192
+ plaintext?: string;
2121
2193
  }): Promise<OutboundKeyDbRow>;
2194
+ outboundApiKeysReveal(id: string): Promise<string | null>;
2195
+ outboundApiKeysDelete(id: string): Promise<boolean>;
2122
2196
  outboundApiKeysRevoke(id: string): Promise<boolean>;
2123
2197
  outboundApiKeysTouchLastUsed(id: string): Promise<boolean>;
2124
2198
  outboundApiKeysSetEnabled(id: string, enabled: boolean): Promise<boolean>;
@@ -2642,6 +2716,7 @@ interface Daemon {
2642
2716
  readonly keyDb: JsonOutboundKeyDb;
2643
2717
  readonly settingsStore: JsonApiServerSettingsStore;
2644
2718
  readonly providerProxy: ProviderProxy;
2719
+ readonly routeLeaseManager: RouteLeaseManager;
2645
2720
  readonly outboundApiServer: OutboundApiServer;
2646
2721
  /**
2647
2722
  * Multi-key load balancer. Wired into the proxy deps slot
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as _omnicross_core from '@omnicross/core';
2
2
  import { OutboundApiServerConfig, Logger, ProviderConfigSource, TransformerService, Transformer, ResolvedTransformerChain, ApiServerSettingsStore, PricingStore, AutomaticPricingSource, OutboundKeyDb, OutboundKeyDbRow, OutboundKeyPolicy, PricingEngine as PricingEngine$1 } from '@omnicross/core';
3
3
  import { ApiKeyPoolService } from '@omnicross/core/completion/ApiKeyPoolService';
4
4
  import { AllowanceSchedulingConfig, AccountProbeConfig, OutboundKeyDb as OutboundKeyDb$1, VoucherDb, KeySpendReader, OutboundApiServer } from '@omnicross/core/outbound-api';
5
- import { ProviderProxy } from '@omnicross/core/provider-proxy';
5
+ import { RouteLeaseManager, ProviderProxy } from '@omnicross/core/provider-proxy';
6
6
  import { UsageRecorder, PricingEngine } from '@omnicross/core/usage';
7
7
  import { SubscriptionCredentialStore, FetchLike, SubscriptionProviderRegistry, SubscriptionAccountService } from '@omnicross/subscriptions';
8
8
  import { AccountAllowanceSnapshot } from '@omnicross/contracts/account-allowance-types';
@@ -15,7 +15,7 @@ import { SubscriptionIdentityStore } from '@omnicross/core/provider-proxy/identi
15
15
  import { LoggingConfig, HealthReport } from '@omnicross/contracts/health-logging-types';
16
16
  import { SubscriptionAccountHealth } from '@omnicross/core/pipeline/SubscriptionAccountHealth';
17
17
  import { fetchUpstream } from '@omnicross/core/pipeline/upstreamFetch';
18
- import { AuditRecord, AuditConfig } from '@omnicross/contracts/audit-types';
18
+ import { AuditRecord, AuditStats, AuditConfig } from '@omnicross/contracts/audit-types';
19
19
  import { BillingDeliveryStatus, BillingConfig, BillingEvent } from '@omnicross/contracts/billing-types';
20
20
  import http from 'node:http';
21
21
  import { LLMProvider, AgentDefaultModels, GlobalModelParameters } from '@omnicross/contracts/llm-config';
@@ -579,6 +579,12 @@ declare class JsonSubscriptionCredentialStore implements SubscriptionCredentialS
579
579
  * TEST-injected `fetchImpl` is returned verbatim; otherwise the refresh routes
580
580
  * through {@link fetchUpstream} with the account's `{ providerId, accountId }`
581
581
  * ctx so the per-account/provider proxy applies. `@internal` also a test seam.
582
+ *
583
+ * `redactBodies` is REQUIRED here: this round-trip sends the refresh_token and
584
+ * receives a fresh access/refresh token pair. Carrying a `providerId` opts the
585
+ * call into the upstream trace (so a failing refresh is diagnosable), and the
586
+ * trace captures bodies verbatim — without this flag every refresh would write
587
+ * a plaintext token pair into `upstream-trace.jsonl`.
582
588
  */
583
589
  buildRefreshFetch(providerId: string, accountId?: string): FetchLike;
584
590
  /**
@@ -923,11 +929,12 @@ interface SubscriptionTokenWriter {
923
929
  * app-parity child 4, design D1).
924
930
  *
925
931
  * `start` mints a crypto-random `sessionId` and stashes the per-session PKCE
926
- * `{ providerId, codeVerifier, state }` here; `complete` does a SINGLE-USE
927
- * `take(sessionId)` (returns + deletes) and exchanges the code. The map is
932
+ * `{ providerId, codeVerifier, state }` here; `complete` `peek`s the session,
933
+ * exchanges the code, and `consume`s it ONLY once a token was minted so a
934
+ * failed exchange leaves the session retryable instead of burning it. The map is
928
935
  * NEVER serialized to the client — only the opaque `sessionId` + the public
929
936
  * `authUrl` cross the wire. Sessions are short-lived (OQ3 = 10-min TTL); a sweep
930
- * reaps abandoned sessions, and `take` re-checks the TTL so an expired-but-not-
937
+ * reaps abandoned sessions, and `peek` re-checks the TTL so an expired-but-not-
931
938
  * yet-swept session is still rejected. A daemon restart simply drops in-flight
932
939
  * logins (correct fail-safe — no partial token is ever written).
933
940
  *
@@ -963,13 +970,25 @@ declare class OAuthSessionStore {
963
970
  */
964
971
  put(session: Omit<PendingOAuthSession, 'createdAt'>): string;
965
972
  /**
966
- * SINGLE-USE consume: return + delete the session for `sessionId`, or `null`
967
- * when it is unknown, already used, or past its TTL (in which case it is
968
- * dropped). A `null` return means the completer must reject (no exchange, no
969
- * write).
973
+ * NON-DESTRUCTIVE lookup: return the session for `sessionId`, or `null` when
974
+ * it is unknown, already consumed, or past its TTL (an expired entry is
975
+ * dropped here). A `null` return means the completer must reject (no
976
+ * exchange, no write).
977
+ *
978
+ * Deliberately NOT a consume: the completer peeks, runs the token exchange,
979
+ * and only {@link consume}s once a token has actually been minted. Consuming
980
+ * up-front burned the session on EVERY failed exchange (a mistyped/expired
981
+ * pasted code, a proxy hiccup), so the user's natural retry hit
982
+ * "session is unknown, expired, or already used" and the login became
983
+ * unrecoverable without restarting the whole flow.
984
+ */
985
+ peek(sessionId: string): PendingOAuthSession | null;
986
+ /**
987
+ * SINGLE-USE burn: drop the session so the same `sessionId` can never be
988
+ * completed twice. Called ONLY after a successful token exchange.
970
989
  */
971
- take(sessionId: string): PendingOAuthSession | null;
972
- /** Drop every session past its TTL. Called on each put/take. */
990
+ consume(sessionId: string): void;
991
+ /** Drop every session past its TTL. Called on each put/peek. */
973
992
  private sweep;
974
993
  }
975
994
 
@@ -983,10 +1002,12 @@ declare class OAuthSessionStore {
983
1002
  * provider's authorize params and stashes the per-session `{ codeVerifier, state }`
984
1003
  * in the `OAuthSessionStore` keyed by a minted opaque `sessionId`, returning ONLY
985
1004
  * `{ authUrl, sessionId }` (the `authUrl` carries client_id + PKCE challenge +
986
- * state — all public). `complete` does a SINGLE-USE `take(sessionId)`, validates
987
- * state (claude's `code#state`), `exchangeCodeForTokens(...)`, persists the minted
988
- * token through the encrypted credential store (`appendProviderAccount`) + marks
989
- * it active, and responds ONLY the sanitized `SubscriptionListEntry`.
1005
+ * state — all public). `complete` `peek`s the session, validates state (claude's
1006
+ * `code#state`), `exchangeCodeForTokens(...)`, then and ONLY then — `consume`s
1007
+ * the session (single-use), persists the minted token through the encrypted
1008
+ * credential store (`appendProviderAccount`) + marks it active, and responds ONLY
1009
+ * the sanitized `SubscriptionListEntry`. A FAILED exchange leaves the session
1010
+ * intact so the user can retry within its TTL instead of being locked out by a 410.
990
1011
  *
991
1012
  * SECRET SPINE (the load-bearing invariant): the minted access/refresh token
992
1013
  * NEVER appears in any response body or log; the `codeVerifier` / session map is
@@ -1283,7 +1304,14 @@ interface ProbeRecord {
1283
1304
  /** Upstream round-trip latency (ms); absent for a local-tier record. */
1284
1305
  latencyMs?: number;
1285
1306
  /** Which tier produced this record. */
1286
- tier: 'local' | 'upstream';
1307
+ tier: 'local' | 'upstream' | 'generation';
1308
+ }
1309
+ /** Secret-free outcome returned by the manual account connection-test route. */
1310
+ interface AccountConnectionProbeOutcome {
1311
+ ok: boolean;
1312
+ marked: boolean;
1313
+ tier: ProbeRecord['tier'];
1314
+ model?: string;
1287
1315
  }
1288
1316
  /** Per-account probe history for the authed admin surface (names account ids). */
1289
1317
  interface AccountProbeHistorySnapshot {
@@ -1303,6 +1331,8 @@ interface AccountProbeHistoryReader {
1303
1331
  interface ProbeCredentialStore {
1304
1332
  getFullConfig(): Promise<AccountTokensConfig>;
1305
1333
  getAccessTokenForAccount(providerId: SubscriptionProviderId, accountId: string): Promise<string | null>;
1334
+ /** Optional serving-parity retry seam for an upstream Codex 401. */
1335
+ refreshAccountToken?(providerId: SubscriptionProviderId, accountId: string): Promise<boolean>;
1306
1336
  }
1307
1337
  /** Proxy-aware upstream fetch signature (#3 `fetchUpstream`). */
1308
1338
  type ProbeFetch = typeof fetchUpstream;
@@ -1352,10 +1382,13 @@ declare class AccountHealthProbeScheduler implements AccountProbeHistoryReader {
1352
1382
  * no upstream); else the upstream tier when a verified endpoint exists. Records
1353
1383
  * the rolling history entry either way; returns whether the tracker was MARKED.
1354
1384
  */
1355
- probeAccount(providerId: SubscriptionProviderId, accountId: string): Promise<{
1356
- ok: boolean;
1357
- marked: boolean;
1358
- }>;
1385
+ probeAccount(providerId: SubscriptionProviderId, accountId: string): Promise<AccountConnectionProbeOutcome>;
1386
+ /**
1387
+ * Manual connection test. Codex performs a real, quota-consuming generation;
1388
+ * every other provider keeps its existing cheap probe. Scheduled sweeps never
1389
+ * call this method, so they remain non-billable.
1390
+ */
1391
+ testAccountConnection(providerId: SubscriptionProviderId, accountId: string): Promise<AccountConnectionProbeOutcome>;
1359
1392
  /** Per-account rolling history for the authed admin surface (design D5). */
1360
1393
  getAllHistory(): AccountProbeHistorySnapshot[];
1361
1394
  /**
@@ -1374,6 +1407,7 @@ declare class AccountHealthProbeScheduler implements AccountProbeHistoryReader {
1374
1407
  private record;
1375
1408
  /** Read a bounded slice of the response body for the 403-ban sniff (never throws). */
1376
1409
  private readBounded;
1410
+ private runCodexGenerationAttempt;
1377
1411
  private key;
1378
1412
  private parseKey;
1379
1413
  }
@@ -1400,6 +1434,18 @@ interface AuditQuery {
1400
1434
  limit?: number;
1401
1435
  }
1402
1436
 
1437
+ /**
1438
+ * Metadata-only audit aggregation. The overview needs request/error counts, not
1439
+ * multi-gigabyte request/response bodies. A compact per-day sidecar is updated
1440
+ * with each new record; legacy files are scanned once with a bounded prefix per
1441
+ * JSONL row and then cached in the same sidecar.
1442
+ */
1443
+
1444
+ interface AuditStatsQuery {
1445
+ from?: number;
1446
+ to?: number;
1447
+ }
1448
+
1403
1449
  /**
1404
1450
  * auditQueryApi — the AUTHED `GET /admin/api/audit?keyId=&from=&to=&limit=`
1405
1451
  * handler (request-audit-log, design D6).
@@ -1419,6 +1465,8 @@ interface AuditQuery {
1419
1465
 
1420
1466
  /** The read surface the AdminServer consumes (bootstrap binds it to the store). */
1421
1467
  type AuditQueryReader = (query: AuditQuery) => AuditRecord[];
1468
+ /** Metadata-only aggregate reader used by the overview. */
1469
+ type AuditStatsReader = (query: AuditStatsQuery) => Promise<AuditStats> | AuditStats;
1422
1470
 
1423
1471
  /**
1424
1472
  * billingStatusApi — the AUTHED `GET /admin/api/billing-status` handler
@@ -1783,6 +1831,7 @@ declare class IntegrationManager {
1783
1831
  /** Injectable PATH probe (tests stub this; default scans `process.env.PATH`). */
1784
1832
  type PathProbe = (candidate: string) => string | null;
1785
1833
  /** Open a NEW terminal window running `command [extraArgs…]` with `env` injected. */
1834
+ type TerminalCleanup = () => void;
1786
1835
  type TerminalOpener = (input: {
1787
1836
  cli: string;
1788
1837
  command: string;
@@ -1790,7 +1839,8 @@ type TerminalOpener = (input: {
1790
1839
  env: Record<string, string>;
1791
1840
  cwd?: string;
1792
1841
  platform: NodeJS.Platform;
1793
- }) => void;
1842
+ onFailure?: () => void;
1843
+ }) => void | TerminalCleanup;
1794
1844
  /**
1795
1845
  * Injectable shell runner for `POST /cli/:cli/install` (tests stub this; the
1796
1846
  * default execs the install command with a bounded timeout). Returns the host's
@@ -1899,6 +1949,8 @@ interface AdminApiDeps {
1899
1949
  readonly settingsStore: JsonApiServerSettingsStore;
1900
1950
  /** The running outbound server (status + live applyConfig). */
1901
1951
  readonly outboundApiServer: OutboundApiServer;
1952
+ /** Process-local machine-managed routing leases (optional for light embedders). */
1953
+ readonly routeLeaseManager?: RouteLeaseManager;
1902
1954
  /** Subscription accounts (token-free `listAll`). */
1903
1955
  readonly subscriptionAccounts: AdminAccountsLister;
1904
1956
  /**
@@ -1914,6 +1966,12 @@ interface AdminApiDeps {
1914
1966
  ok: boolean;
1915
1967
  marked: boolean;
1916
1968
  }>;
1969
+ testAccountConnection(providerId: _omnicross_contracts_subscription_types.SubscriptionProviderId, accountId: string): Promise<{
1970
+ ok: boolean;
1971
+ marked: boolean;
1972
+ tier: 'local' | 'upstream' | 'generation';
1973
+ model?: string;
1974
+ }>;
1917
1975
  };
1918
1976
  /**
1919
1977
  * Least-authority subscription-token WRITER (design D4) — ONLY the mutation
@@ -1936,11 +1994,13 @@ interface AdminApiDeps {
1936
1994
  */
1937
1995
  readonly oauthSessions: OAuthSessionStore;
1938
1996
  /**
1939
- * Injected token-exchange `FetchLike` (oauth design D2-a) — defaults to global
1940
- * `fetch` in `bootstrap.ts`; tests inject a mock so no real token endpoint is
1941
- * hit. Mirrors how `login.ts` injects its exchange fetch.
1997
+ * Injected token-exchange `FetchLike` FACTORY (oauth design D2-a) — built per
1998
+ * provider in `bootstrap.ts` so the exchange carries a `{ providerId }` egress
1999
+ * ctx (per-provider proxy layer + upstream trace, bodies redacted); tests
2000
+ * inject a mock so no real token endpoint is hit. Mirrors how `login.ts`
2001
+ * injects its exchange fetch.
1942
2002
  */
1943
- readonly oauthExchangeFetch: FetchLike;
2003
+ readonly oauthExchangeFetch: (providerId: SubscriptionProviderId) => FetchLike;
1944
2004
  /**
1945
2005
  * NARROW append handle (oauth design D2-a) — the OAuth complete handler needs
1946
2006
  * `appendProviderAccount` (NOT on the least-authority `SubscriptionTokenWriter`).
@@ -2062,6 +2122,8 @@ interface AdminServerDeps extends AdminApiDeps {
2062
2122
  * unauthenticated, NEVER on `/health`.
2063
2123
  */
2064
2124
  auditReader?: AuditQueryReader;
2125
+ /** Metadata-only audit aggregate used by the overview error-rate metric. */
2126
+ auditStatsReader?: AuditStatsReader;
2065
2127
  /**
2066
2128
  * OPTIONAL billing delivery-status reader (billing-event-stream, design D5).
2067
2129
  * When wired (bootstrap → the ledger dir), the AUTHED `GET /admin/api/billing-status`
@@ -2106,7 +2168,16 @@ declare class AdminServer {
2106
2168
 
2107
2169
  declare class JsonOutboundKeyDb implements OutboundKeyDb {
2108
2170
  private readonly keysPath;
2109
- constructor(keysPath: string);
2171
+ private readonly secretBox?;
2172
+ /**
2173
+ * @param secretBox OPTIONAL reversible-secret codec. When present, a created
2174
+ * key's plaintext is persisted as a `keySecret` `enc:` envelope (enabling the
2175
+ * operator "view key" affordance via `outboundApiKeysReveal`). When absent the
2176
+ * store stays hash-only (byte-identical to the legacy behavior) and reveal
2177
+ * always returns `null`. Existing 1-arg call sites (tests, lightweight
2178
+ * embedders) keep working.
2179
+ */
2180
+ constructor(keysPath: string, secretBox?: SecretBox | undefined);
2110
2181
  outboundApiKeysList(): Promise<OutboundKeyDbRow[]>;
2111
2182
  outboundApiKeysGetByHash(hash: string): Promise<OutboundKeyDbRow | null>;
2112
2183
  outboundApiKeysCreate(input: {
@@ -2118,7 +2189,10 @@ declare class JsonOutboundKeyDb implements OutboundKeyDb {
2118
2189
  kind?: 'client' | 'integration';
2119
2190
  allowedEndpoints?: _omnicross_core.OutboundEndpoint[];
2120
2191
  loopbackOnly?: boolean;
2192
+ plaintext?: string;
2121
2193
  }): Promise<OutboundKeyDbRow>;
2194
+ outboundApiKeysReveal(id: string): Promise<string | null>;
2195
+ outboundApiKeysDelete(id: string): Promise<boolean>;
2122
2196
  outboundApiKeysRevoke(id: string): Promise<boolean>;
2123
2197
  outboundApiKeysTouchLastUsed(id: string): Promise<boolean>;
2124
2198
  outboundApiKeysSetEnabled(id: string, enabled: boolean): Promise<boolean>;
@@ -2642,6 +2716,7 @@ interface Daemon {
2642
2716
  readonly keyDb: JsonOutboundKeyDb;
2643
2717
  readonly settingsStore: JsonApiServerSettingsStore;
2644
2718
  readonly providerProxy: ProviderProxy;
2719
+ readonly routeLeaseManager: RouteLeaseManager;
2645
2720
  readonly outboundApiServer: OutboundApiServer;
2646
2721
  /**
2647
2722
  * Multi-key load balancer. Wired into the proxy deps slot