Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
2c56c36
feat(credential-proxy): add bounded bearer forwarding
Nov 11, 2026
41d09a3
feat(credential-proxy): stream authorized tunnel requests
Nov 11, 2026
f00b2f0
feat(credential-proxy): connect authenticated VM tunnel
Nov 11, 2026
08fddf2
Bind enrollment acceptance to proxy boot epoch
Nov 11, 2026
adfefc5
Bind tunnel enrollment to authenticated VM peer
Nov 11, 2026
5b44328
Add authenticated proxy boot registration
Nov 11, 2026
1ed566e
Add secure proxy bootstrap provisioning boundary
Nov 11, 2026
edf98ea
Provision credential proxy with isolated bootstrap
Nov 11, 2026
e631553
Retry proxy tunnel enrollment before forwarding
Nov 11, 2026
545d9e7
Add authenticated proxy enrollment control API
Nov 11, 2026
f1ff6ad
Wire proxy-side run enrollment into tunnel auth
Nov 11, 2026
b4462a2
Wire proxy control enrollment into tunnel startup
Nov 11, 2026
a96a584
Merge remote-tracking branch 'origin/main' into GEN-2824-proxy-forwar…
Nov 11, 2026
ef4b952
Retain proxy control credential after boot registration
Nov 11, 2026
59e6bea
Authenticate tunnel enrollment with run credential
Nov 11, 2026
2188c7d
Keep run credential out of consume request
Nov 11, 2026
78b86ee
Cover invalid run enrollment bindings
Nov 11, 2026
c46c3a2
Narrow active run identity before enrollment
Nov 11, 2026
fd74010
Close proxy tunnels when a run is revoked
Nov 11, 2026
68d348e
Add decrypted run integration grant resolver
Nov 11, 2026
eb90329
Expose selected integrations to authenticated proxy
Nov 11, 2026
3e79721
Merge remote-tracking branch 'origin/main' into GEN-2824-proxy-forwar…
Nov 11, 2026
6f13d7b
Fix encrypted snapshot proxy test fixture
Nov 11, 2026
fea379c
Wire proxy snapshots into local grant resolution
Nov 11, 2026
b765691
Preserve grant resolver selection boundaries
Nov 11, 2026
15335fa
Resolve empty and locked grants safely
Nov 11, 2026
32414a2
Match snapshot control request contract
Nov 11, 2026
c22a412
Bind tunnel VM identity to certificate SAN
Nov 11, 2026
3ed3f07
GEN-2824 provision mTLS identities and revoke tunnels
Nov 11, 2026
a3aad85
GEN-2824 include selected model account snapshot
Nov 11, 2026
463ce53
GEN-2824 update snapshot fixture for model selection
Nov 12, 2026
44c5bde
GEN-2824 add isolated Codex auth helper
Nov 12, 2026
69f05bc
GEN-2824 persist encrypted Codex account refreshes
Nov 12, 2026
454232c
GEN-2824 encrypt Codex account caches in proxy
Nov 12, 2026
28f8f1c
GEN-2824 restore encrypted Codex caches on unlock
Nov 12, 2026
d27d95a
GEN-2824 persist encrypted model caches by revision
Nov 12, 2026
df221e5
GEN-2824 compose model cache lifecycle into proxy startup
Nov 12, 2026
a20d434
GEN-2824 add private browser model authorization control
Nov 12, 2026
c876176
GEN-2824 issue paired model account browser capabilities
Nov 12, 2026
dd266cc
GEN-2824 connect model account browser authorization
Nov 12, 2026
2ccb27b
GEN-2824 cover capability endpoint in browser test
Nov 12, 2026
87341ad
GEN-2824 add model account create and delete
Nov 12, 2026
4e4a5c0
GEN-2824 recover stale model account cache writes
Nov 12, 2026
e5a6a97
GEN-2824 clear deleted model caches on unlock
Nov 12, 2026
29cd548
GEN-2824 cover model cache key rotation race
Nov 12, 2026
7a4fdfa
GEN-2824 cover model reset refresh race
Nov 12, 2026
5a5f01a
GEN-2824 cover reset during refresh retry
Nov 12, 2026
8960123
GEN-2824 invalidate refresh retries after model rotation
Nov 12, 2026
e627df1
GEN-2824 define portable proxy launch gates
Nov 12, 2026
e85bf4a
GEN-2824 disable Fly job machine restarts
Nov 12, 2026
1f25532
GEN-2824 persist proxy launch blocks and manual retry
Nov 12, 2026
eda72e9
Merge origin/main into GEN-2824 proxy launch work
Nov 12, 2026
eca2eca
feat(credential-proxy): add bounded bearer forwarding
Nov 11, 2026
a6a282f
feat(credential-proxy): stream authorized tunnel requests
Nov 11, 2026
f1d2c84
feat(credential-proxy): connect authenticated VM tunnel
Nov 11, 2026
8c6be50
Bind enrollment acceptance to proxy boot epoch
Nov 11, 2026
1ec0345
Bind tunnel enrollment to authenticated VM peer
Nov 11, 2026
4ae0b74
Add authenticated proxy boot registration
Nov 11, 2026
56fd6c2
Add secure proxy bootstrap provisioning boundary
Nov 11, 2026
6df5360
Provision credential proxy with isolated bootstrap
Nov 11, 2026
207d68f
Retry proxy tunnel enrollment before forwarding
Nov 11, 2026
497f4bd
Add authenticated proxy enrollment control API
Nov 11, 2026
516938c
Wire proxy-side run enrollment into tunnel auth
Nov 11, 2026
8c35922
Wire proxy control enrollment into tunnel startup
Nov 11, 2026
712f6fe
Retain proxy control credential after boot registration
Nov 11, 2026
f5fcd51
Authenticate tunnel enrollment with run credential
Nov 11, 2026
3fcb724
Keep run credential out of consume request
Nov 11, 2026
62b0729
Cover invalid run enrollment bindings
Nov 11, 2026
9e85768
Narrow active run identity before enrollment
Nov 11, 2026
ced6454
Close proxy tunnels when a run is revoked
Nov 11, 2026
184cd43
Add decrypted run integration grant resolver
Nov 11, 2026
7457e58
Expose selected integrations to authenticated proxy
Nov 11, 2026
af71a90
Fix encrypted snapshot proxy test fixture
Nov 11, 2026
69fa35e
Wire proxy snapshots into local grant resolution
Nov 11, 2026
3467c03
Preserve grant resolver selection boundaries
Nov 11, 2026
a3a74a2
Resolve empty and locked grants safely
Nov 11, 2026
2872e4e
Match snapshot control request contract
Nov 11, 2026
41f35d1
Bind tunnel VM identity to certificate SAN
Nov 11, 2026
434c008
GEN-2824 provision mTLS identities and revoke tunnels
Nov 11, 2026
41b91d2
GEN-2824 include selected model account snapshot
Nov 11, 2026
1411909
GEN-2824 update snapshot fixture for model selection
Nov 12, 2026
850e36a
GEN-2824 add isolated Codex auth helper
Nov 12, 2026
75f9df0
GEN-2824 persist encrypted Codex account refreshes
Nov 12, 2026
32cc5b7
GEN-2824 encrypt Codex account caches in proxy
Nov 12, 2026
d5c433b
GEN-2824 restore encrypted Codex caches on unlock
Nov 12, 2026
4653583
GEN-2824 persist encrypted model caches by revision
Nov 12, 2026
182b8bf
GEN-2824 compose model cache lifecycle into proxy startup
Nov 12, 2026
555656a
GEN-2824 add private browser model authorization control
Nov 12, 2026
96d8272
GEN-2824 issue paired model account browser capabilities
Nov 12, 2026
8a68534
GEN-2824 connect model account browser authorization
Nov 12, 2026
6e81b33
GEN-2824 cover capability endpoint in browser test
Nov 12, 2026
834e2b3
GEN-2824 add model account create and delete
Nov 12, 2026
b99aa42
GEN-2824 recover stale model account cache writes
Nov 12, 2026
4883c88
GEN-2824 clear deleted model caches on unlock
Nov 12, 2026
1d56983
GEN-2824 cover model cache key rotation race
Nov 12, 2026
6ed5e76
GEN-2824 cover model reset refresh race
Nov 12, 2026
4b67c2a
GEN-2824 cover reset during refresh retry
Nov 12, 2026
3981a80
GEN-2824 invalidate refresh retries after model rotation
Nov 12, 2026
3414c7b
GEN-2824 define portable proxy launch gates
Nov 12, 2026
6d29321
GEN-2824 disable Fly job machine restarts
Nov 12, 2026
a5c6d8d
GEN-2824 persist proxy launch blocks and manual retry
Nov 12, 2026
cdf1d02
Merge remote-tracking branch 'origin/main' into GEN-2824-proxy-forwar…
Nov 12, 2026
28dd751
GEN-2824 report proxy unlock state to scheduler
Nov 12, 2026
02492a0
Merge remote-tracking branch 'origin/GEN-2824-proxy-forwarding' into …
Nov 12, 2026
f2ac3f9
GEN-2824 persist blocked proxy launch state
Nov 12, 2026
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
311 changes: 311 additions & 0 deletions packages/api-client/src/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,85 @@
// Generated from packages/docs/openapi.yaml. Do not edit.
export interface paths {
"/api/v1/model-accounts": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* List model accounts available to the owner
* @description Requires an interactive owner browser session. Returns account metadata and the collection revision only; encrypted account caches and credentials are never returned.
*
* Requires the integrations:read scope.
*
* An interactive owner session is required; bearer tokens cannot call this operation.
*/
get: operations["get_api_v1_model_accounts"];
put?: never;
/**
* Create a model account
* @description Requires an interactive owner browser session and the current collection revision. Accepts only user-encrypted initial account state; credentials are established directly with the credential proxy.
*
* Requires the integrations:write scope.
*
* An interactive owner session is required; bearer tokens cannot call this operation.
*/
post: operations["post_api_v1_model_accounts"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/model-accounts/{accountId}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/**
* Delete a model account
* @description Requires an interactive owner browser session and the current collection revision. Deletion is recorded as a tombstone so future snapshots and unlock reconciliation cannot restore the account.
*
* Requires the integrations:write scope.
*
* An interactive owner session is required; bearer tokens cannot call this operation.
*/
delete: operations["delete_api_v1_model_accounts_accountId"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/model-accounts/{accountId}/browser-capability": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Issue a short-lived browser capability for a paired model account
* @description Requires an interactive owner browser session. Returns a single-use, 60-second capability scoped to the account, action, proxy boot and exact application origin. The browser sends it directly to the paired proxy; Factorize never receives model-account tokens.
*
* Requires the integrations:write scope.
*
* An interactive owner session is required; bearer tokens cannot call this operation.
*/
post: operations["post_api_v1_model_accounts_accountId_browser_capability"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/unlock-key/verification": {
parameters: {
query?: never;
Expand Down Expand Up @@ -1988,6 +2068,30 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/v1/runs/{runId}/retry-launch": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Manually retry a blocked launch
* @description Retries only a pre-launch proxy-gated run after its prerequisites have been resolved. The run remains blocked until an interactive owner explicitly retries it; unlock or status changes do not automatically launch it.
*
* Requires the runs:cancel scope.
*
* An interactive owner session is required; bearer tokens cannot call this operation.
*/
post: operations["post_api_v1_runs_runId_retry_launch"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/runs/{runId}/kill": {
parameters: {
query?: never;
Expand Down Expand Up @@ -2683,6 +2787,176 @@ export interface components {
}
export type $defs = Record<string, never>;
export interface operations {
get_api_v1_model_accounts: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Model account metadata and collection revision */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
revision: number;
accounts: {
/** Format: uuid */
id: string;
name: string;
description: string | null;
revision: number;
}[];
};
};
};
400: components["responses"]["Error400"];
401: components["responses"]["Error401"];
403: components["responses"]["Error403"];
404: components["responses"]["Error404"];
409: components["responses"]["Error409"];
429: components["responses"]["Error429"];
500: components["responses"]["Error500"];
503: components["responses"]["Error503"];
};
};
post_api_v1_model_accounts: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** Format: uuid */
id: string;
expectedRevision: number;
/** Format: uuid */
idempotencyKey: string;
name: string;
description: string | null;
encryptedPayload: string;
};
};
};
responses: {
/** @description Created model account */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
revision: number;
duplicate: boolean;
};
};
};
400: components["responses"]["Error400"];
401: components["responses"]["Error401"];
403: components["responses"]["Error403"];
404: components["responses"]["Error404"];
409: components["responses"]["Error409"];
415: components["responses"]["Error415"];
429: components["responses"]["Error429"];
500: components["responses"]["Error500"];
503: components["responses"]["Error503"];
};
};
delete_api_v1_model_accounts_accountId: {
parameters: {
query?: never;
header?: never;
path: {
accountId: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
expectedRevision: number;
/** Format: uuid */
idempotencyKey: string;
};
};
};
responses: {
/** @description Deleted model account */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
/** Format: uuid */
id: string;
/** @constant */
deleted: true;
revision: number;
duplicate: boolean;
};
};
};
400: components["responses"]["Error400"];
401: components["responses"]["Error401"];
403: components["responses"]["Error403"];
404: components["responses"]["Error404"];
409: components["responses"]["Error409"];
415: components["responses"]["Error415"];
429: components["responses"]["Error429"];
500: components["responses"]["Error500"];
503: components["responses"]["Error503"];
};
};
post_api_v1_model_accounts_accountId_browser_capability: {
parameters: {
query?: never;
header?: never;
path: {
accountId: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** @enum {string} */
action: "authorize" | "status" | "cancel";
};
};
};
responses: {
/** @description Paired proxy endpoint and one-use capability */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
/** Format: uri */
endpoint: string;
capability: string;
};
};
};
400: components["responses"]["Error400"];
401: components["responses"]["Error401"];
403: components["responses"]["Error403"];
404: components["responses"]["Error404"];
409: components["responses"]["Error409"];
415: components["responses"]["Error415"];
429: components["responses"]["Error429"];
500: components["responses"]["Error500"];
503: components["responses"]["Error503"];
};
};
get_api_v1_unlock_key_verification: {
parameters: {
query?: never;
Expand Down Expand Up @@ -7956,6 +8230,43 @@ export interface operations {
503: components["responses"]["Error503"];
};
};
post_api_v1_runs_runId_retry_launch: {
parameters: {
query?: never;
header?: never;
path: {
runId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Manual retry queued */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
/** Format: uuid */
runId: string;
/** @constant */
retryRequested: true;
};
};
};
400: components["responses"]["Error400"];
401: components["responses"]["Error401"];
/** @description Interactive owner session required */
403: components["responses"]["Error403"];
404: components["responses"]["Error404"];
/** @description Run is not waiting for a manual launch retry */
409: components["responses"]["Error409"];
429: components["responses"]["Error429"];
500: components["responses"]["Error500"];
503: components["responses"]["Error503"];
};
};
post_api_v1_runs_runId_kill: {
parameters: {
query?: never;
Expand Down
10 changes: 10 additions & 0 deletions packages/api/migrations/0036_proxy_control_credentials.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE app.credential_proxy_control_credentials (
tenant_id uuid NOT NULL REFERENCES app.tenants(id) ON DELETE CASCADE,
proxy_identity text NOT NULL,
boot_epoch uuid NOT NULL,
token_digest bytea NOT NULL UNIQUE,
revoked_at timestamptz,
consumed_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (tenant_id, proxy_identity)
);
2 changes: 2 additions & 0 deletions packages/api/migrations/0037_proxy_control_credentials.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE app.credential_proxy_control_credentials
ADD COLUMN proxy_token_digest bytea UNIQUE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE app.credential_proxy_browser_pairings (
tenant_id uuid PRIMARY KEY REFERENCES app.tenants(id) ON DELETE CASCADE,
proxy_identity text NOT NULL,
boot_epoch uuid NOT NULL,
browser_origin text NOT NULL,
updated_at timestamptz NOT NULL DEFAULT now(),
CHECK (browser_origin ~ '^https://[^/]+$')
);
2 changes: 2 additions & 0 deletions packages/api/migrations/0047_proxy_launch_status.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE app.credential_proxy_states
ADD COLUMN unlocked boolean NOT NULL DEFAULT false;
Loading