@pleri/olam-cli 0.1.173 → 0.1.175
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/commands/auth.d.ts +22 -7
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +414 -46
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +45 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/services.d.ts +39 -0
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +64 -9
- package/dist/commands/services.js.map +1 -1
- package/dist/from-manifest.d.ts +53 -0
- package/dist/from-manifest.d.ts.map +1 -0
- package/dist/from-manifest.js +95 -0
- package/dist/from-manifest.js.map +1 -0
- package/dist/image-digests.json +8 -8
- package/dist/index.js +907 -136
- package/dist/lib/auth-remote.d.ts +130 -0
- package/dist/lib/auth-remote.d.ts.map +1 -0
- package/dist/lib/auth-remote.js +307 -0
- package/dist/lib/auth-remote.js.map +1 -0
- package/dist/mcp-server.js +254 -57
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/src/boot-reconciler.mjs +238 -0
- package/host-cp/src/port-bridge-manager.mjs +116 -10
- package/host-cp/src/server.mjs +32 -0
- package/host-cp/src/world-activity-tracker.mjs +392 -0
- package/package.json +1 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auth-remote — HTTP helper for `olam auth --remote <url>` subcommands.
|
|
3
|
+
*
|
|
4
|
+
* Wraps fetch calls against the auth-worker's `/v1/*` endpoints.
|
|
5
|
+
*
|
|
6
|
+
* V1 dogfood note: CF Access cookie must be obtained manually via browser.
|
|
7
|
+
* A proper CLI-orchestrated SSO flow (CLI-as-OAuth-client) is deferred to v2.
|
|
8
|
+
* See e4/e5/e6 task notes in docs/plans/auth-worker-multitenant-vault/.
|
|
9
|
+
*/
|
|
10
|
+
export type FetchFn = typeof fetch;
|
|
11
|
+
export interface RemoteClientOptions {
|
|
12
|
+
/** Auth-worker base URL, e.g. https://auth.example.workers.dev */
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
/** CF_Authorization cookie value, obtained manually from browser DevTools. */
|
|
15
|
+
cfAuthCookie?: string;
|
|
16
|
+
/** Injected fetch for testing. Defaults to global fetch. */
|
|
17
|
+
fetchFn?: FetchFn;
|
|
18
|
+
}
|
|
19
|
+
export interface ServiceToken {
|
|
20
|
+
client_id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
created_at?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface AccountEntry {
|
|
25
|
+
id: string;
|
|
26
|
+
label?: string;
|
|
27
|
+
state?: string;
|
|
28
|
+
expiresIn?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface AnthropicTokenIssueResponse {
|
|
31
|
+
secret: string;
|
|
32
|
+
token_hash: string;
|
|
33
|
+
label: string;
|
|
34
|
+
anthropic_base_url_hint?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface AnthropicTokenEntry {
|
|
37
|
+
token_hash: string;
|
|
38
|
+
label: string;
|
|
39
|
+
issued_at?: string;
|
|
40
|
+
created_at?: string;
|
|
41
|
+
last_used_at?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface OAuthStartResponse {
|
|
44
|
+
authorize_url: string;
|
|
45
|
+
state_id: string;
|
|
46
|
+
}
|
|
47
|
+
export interface HealthResponse {
|
|
48
|
+
status: string;
|
|
49
|
+
version?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface DoctorCheckResult {
|
|
52
|
+
probe: string;
|
|
53
|
+
status: 'pass' | 'fail' | 'warn';
|
|
54
|
+
message: string;
|
|
55
|
+
remedy?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* GET /v1/health — worker liveness probe.
|
|
59
|
+
*/
|
|
60
|
+
export declare function remoteHealth(opts: RemoteClientOptions): Promise<HealthResponse>;
|
|
61
|
+
/**
|
|
62
|
+
* POST /v1/oauth/start — begin an OAuth flow.
|
|
63
|
+
* Returns { authorize_url, state_id }.
|
|
64
|
+
*/
|
|
65
|
+
export declare function remoteOAuthStart(opts: RemoteClientOptions): Promise<OAuthStartResponse>;
|
|
66
|
+
/**
|
|
67
|
+
* GET /v1/service-tokens — list bound service tokens.
|
|
68
|
+
*/
|
|
69
|
+
export declare function remoteListServiceTokens(opts: RemoteClientOptions): Promise<ServiceToken[]>;
|
|
70
|
+
/**
|
|
71
|
+
* GET /v1/accounts — list registered accounts (Anthropic OAuth sessions).
|
|
72
|
+
*/
|
|
73
|
+
export declare function remoteListAccounts(opts: RemoteClientOptions): Promise<AccountEntry[]>;
|
|
74
|
+
/**
|
|
75
|
+
* POST /v1/service-tokens/bind — bind a CF service token to a user sub.
|
|
76
|
+
*/
|
|
77
|
+
export declare function remoteBindServiceToken(opts: RemoteClientOptions, payload: {
|
|
78
|
+
client_id: string;
|
|
79
|
+
label: string;
|
|
80
|
+
}): Promise<{
|
|
81
|
+
ok: boolean;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* DELETE /v1/service-tokens/:client_id — revoke a service token.
|
|
85
|
+
*/
|
|
86
|
+
export declare function remoteDeleteServiceToken(opts: RemoteClientOptions, clientId: string): Promise<{
|
|
87
|
+
ok: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
// ── g4: Anthropic proxy token helpers ────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
export interface AnthropicTokenIssueResponse {
|
|
93
|
+
secret: string;
|
|
94
|
+
token_hash: string;
|
|
95
|
+
label: string;
|
|
96
|
+
anthropic_base_url_hint: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface AnthropicTokenEntry {
|
|
100
|
+
label: string;
|
|
101
|
+
token_hash: string;
|
|
102
|
+
issued_at?: string;
|
|
103
|
+
last_used_at?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* POST /v1/anthropic-tokens/issue — mint a new Anthropic proxy token.
|
|
108
|
+
* Returns { secret, token_hash, label, anthropic_base_url_hint }.
|
|
109
|
+
*/
|
|
110
|
+
export declare function remoteIssueAnthropicToken(opts: RemoteClientOptions, label: string): Promise<AnthropicTokenIssueResponse>;
|
|
111
|
+
/**
|
|
112
|
+
* GET /v1/anthropic-tokens — list issued Anthropic proxy tokens.
|
|
113
|
+
*/
|
|
114
|
+
export declare function remoteListAnthropicTokens(opts: RemoteClientOptions): Promise<AnthropicTokenEntry[]>;
|
|
115
|
+
/**
|
|
116
|
+
* DELETE /v1/anthropic-tokens/:token_hash — revoke an Anthropic proxy token.
|
|
117
|
+
* Returns true on 200/204, false on 404.
|
|
118
|
+
*/
|
|
119
|
+
export declare function remoteRevokeAnthropicToken(opts: RemoteClientOptions, tokenHash: string): Promise<boolean>;
|
|
120
|
+
/**
|
|
121
|
+
* runDoctorChecks — runs 4 diagnostic probes against the auth-worker.
|
|
122
|
+
* Returns an ordered array of DoctorCheckResult (pass/fail/warn + remedy).
|
|
123
|
+
*
|
|
124
|
+
* Probe 1: GET /v1/health → liveness
|
|
125
|
+
* Probe 2: CF Access JWKS reachable (derives team domain from worker URL)
|
|
126
|
+
* Probe 3: POST /v1/oauth/start → endpoint reachability
|
|
127
|
+
* Probe 4: ANTHROPIC_OAUTH_CLIENT_ID env present (config check)
|
|
128
|
+
*/
|
|
129
|
+
export declare function runDoctorChecks(opts: RemoteClientOptions): Promise<DoctorCheckResult[]>;
|
|
130
|
+
//# sourceMappingURL=auth-remote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-remote.d.ts","sourceRoot":"","sources":["../../src/lib/auth-remote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auth-remote — HTTP helper for `olam auth --remote <url>` subcommands.
|
|
3
|
+
*
|
|
4
|
+
* Wraps fetch calls against the auth-worker's `/v1/*` endpoints.
|
|
5
|
+
*
|
|
6
|
+
* V1 dogfood note: CF Access cookie must be obtained manually via browser.
|
|
7
|
+
* A proper CLI-orchestrated SSO flow (CLI-as-OAuth-client) is deferred to v2.
|
|
8
|
+
* See e4/e5/e6 task notes in docs/plans/auth-worker-multitenant-vault/.
|
|
9
|
+
*/
|
|
10
|
+
function normalizeBase(url) {
|
|
11
|
+
return url.replace(/\/+$/, '');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build common headers for auth-worker requests.
|
|
15
|
+
* When cfAuthCookie is provided, forwards it so the worker's CF Access
|
|
16
|
+
* middleware can authenticate the request server-side.
|
|
17
|
+
*/
|
|
18
|
+
function buildHeaders(cookie) {
|
|
19
|
+
const headers = {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
};
|
|
23
|
+
if (cookie) {
|
|
24
|
+
headers['Cookie'] = `CF_Authorization=${cookie}`;
|
|
25
|
+
}
|
|
26
|
+
return headers;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* GET /v1/health — worker liveness probe.
|
|
30
|
+
*/
|
|
31
|
+
export async function remoteHealth(opts) {
|
|
32
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
33
|
+
const url = `${normalizeBase(baseUrl)}/v1/health`;
|
|
34
|
+
const res = await fetchFn(url, {
|
|
35
|
+
method: 'GET',
|
|
36
|
+
headers: buildHeaders(cfAuthCookie),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
throw new Error(`Health check failed: HTTP ${res.status}`);
|
|
40
|
+
}
|
|
41
|
+
return res.json();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* POST /v1/oauth/start — begin an OAuth flow.
|
|
45
|
+
* Returns { authorize_url, state_id }.
|
|
46
|
+
*/
|
|
47
|
+
export async function remoteOAuthStart(opts) {
|
|
48
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
49
|
+
const url = `${normalizeBase(baseUrl)}/v1/oauth/start`;
|
|
50
|
+
const res = await fetchFn(url, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: buildHeaders(cfAuthCookie),
|
|
53
|
+
body: JSON.stringify({}),
|
|
54
|
+
});
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
const body = await res.text().catch(() => '');
|
|
57
|
+
throw new Error(`OAuth start failed: HTTP ${res.status}${body ? ` — ${body}` : ''}`);
|
|
58
|
+
}
|
|
59
|
+
return res.json();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* GET /v1/service-tokens — list bound service tokens.
|
|
63
|
+
*/
|
|
64
|
+
export async function remoteListServiceTokens(opts) {
|
|
65
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
66
|
+
const url = `${normalizeBase(baseUrl)}/v1/service-tokens`;
|
|
67
|
+
const res = await fetchFn(url, {
|
|
68
|
+
method: 'GET',
|
|
69
|
+
headers: buildHeaders(cfAuthCookie),
|
|
70
|
+
});
|
|
71
|
+
if (!res.ok) {
|
|
72
|
+
throw new Error(`List service-tokens failed: HTTP ${res.status}`);
|
|
73
|
+
}
|
|
74
|
+
return res.json();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* GET /v1/accounts — list registered accounts (Anthropic OAuth sessions).
|
|
78
|
+
*/
|
|
79
|
+
export async function remoteListAccounts(opts) {
|
|
80
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
81
|
+
const url = `${normalizeBase(baseUrl)}/v1/accounts`;
|
|
82
|
+
const res = await fetchFn(url, {
|
|
83
|
+
method: 'GET',
|
|
84
|
+
headers: buildHeaders(cfAuthCookie),
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
throw new Error(`List accounts failed: HTTP ${res.status}`);
|
|
88
|
+
}
|
|
89
|
+
return res.json();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* POST /v1/service-tokens/bind — bind a CF service token to a user sub.
|
|
93
|
+
*/
|
|
94
|
+
export async function remoteBindServiceToken(opts, payload) {
|
|
95
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
96
|
+
const url = `${normalizeBase(baseUrl)}/v1/service-tokens/bind`;
|
|
97
|
+
const res = await fetchFn(url, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: buildHeaders(cfAuthCookie),
|
|
100
|
+
body: JSON.stringify(payload),
|
|
101
|
+
});
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
const body = await res.text().catch(() => '');
|
|
104
|
+
throw new Error(`Bind service-token failed: HTTP ${res.status}${body ? ` — ${body}` : ''}`);
|
|
105
|
+
}
|
|
106
|
+
return { ok: true };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* DELETE /v1/service-tokens/:client_id — revoke a service token.
|
|
110
|
+
*/
|
|
111
|
+
export async function remoteDeleteServiceToken(opts, clientId) {
|
|
112
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
113
|
+
const url = `${normalizeBase(baseUrl)}/v1/service-tokens/${encodeURIComponent(clientId)}`;
|
|
114
|
+
const res = await fetchFn(url, {
|
|
115
|
+
method: 'DELETE',
|
|
116
|
+
headers: buildHeaders(cfAuthCookie),
|
|
117
|
+
});
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
throw new Error(`Delete service-token failed: HTTP ${res.status}`);
|
|
120
|
+
}
|
|
121
|
+
return { ok: true };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
// ── g4: Anthropic proxy token helpers ────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
export interface AnthropicTokenIssueResponse {
|
|
127
|
+
secret: string;
|
|
128
|
+
token_hash: string;
|
|
129
|
+
label: string;
|
|
130
|
+
anthropic_base_url_hint: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface AnthropicTokenEntry {
|
|
134
|
+
label: string;
|
|
135
|
+
token_hash: string;
|
|
136
|
+
issued_at?: string;
|
|
137
|
+
last_used_at?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* POST /v1/anthropic-tokens/issue — mint a new Anthropic proxy token.
|
|
142
|
+
* Returns { secret, token_hash, label, anthropic_base_url_hint }.
|
|
143
|
+
*/
|
|
144
|
+
export async function remoteIssueAnthropicToken(opts, label) {
|
|
145
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
146
|
+
const url = `${normalizeBase(baseUrl)}/v1/anthropic-tokens/issue`;
|
|
147
|
+
const res = await fetchFn(url, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: buildHeaders(cfAuthCookie),
|
|
150
|
+
body: JSON.stringify({ label }),
|
|
151
|
+
});
|
|
152
|
+
if (!res.ok) {
|
|
153
|
+
const body = await res.text().catch(() => '');
|
|
154
|
+
throw new Error(`Issue anthropic-token failed: HTTP ${res.status}${body ? ` — ${body}` : ''}`);
|
|
155
|
+
}
|
|
156
|
+
return res.json();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* GET /v1/anthropic-tokens — list issued Anthropic proxy tokens.
|
|
160
|
+
*/
|
|
161
|
+
export async function remoteListAnthropicTokens(opts) {
|
|
162
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
163
|
+
const url = `${normalizeBase(baseUrl)}/v1/anthropic-tokens`;
|
|
164
|
+
const res = await fetchFn(url, {
|
|
165
|
+
method: 'GET',
|
|
166
|
+
headers: buildHeaders(cfAuthCookie),
|
|
167
|
+
});
|
|
168
|
+
if (!res.ok) {
|
|
169
|
+
const body = await res.text().catch(() => '');
|
|
170
|
+
throw new Error(`List anthropic-tokens failed: HTTP ${res.status}${body ? ` — ${body}` : ''}`);
|
|
171
|
+
}
|
|
172
|
+
return res.json();
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* DELETE /v1/anthropic-tokens/:token_hash — revoke an Anthropic proxy token.
|
|
176
|
+
* Returns true on 200/204, false on 404.
|
|
177
|
+
*/
|
|
178
|
+
export async function remoteRevokeAnthropicToken(opts, tokenHash) {
|
|
179
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
180
|
+
const url = `${normalizeBase(baseUrl)}/v1/anthropic-tokens/${encodeURIComponent(tokenHash)}`;
|
|
181
|
+
const res = await fetchFn(url, {
|
|
182
|
+
method: 'DELETE',
|
|
183
|
+
headers: buildHeaders(cfAuthCookie),
|
|
184
|
+
});
|
|
185
|
+
if (res.status === 404)
|
|
186
|
+
return false;
|
|
187
|
+
if (!res.ok) {
|
|
188
|
+
throw new Error(`Revoke anthropic-token failed: HTTP ${res.status}`);
|
|
189
|
+
}
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* runDoctorChecks — runs 4 diagnostic probes against the auth-worker.
|
|
194
|
+
* Returns an ordered array of DoctorCheckResult (pass/fail/warn + remedy).
|
|
195
|
+
*
|
|
196
|
+
* Probe 1: GET /v1/health → liveness
|
|
197
|
+
* Probe 2: CF Access JWKS reachable (derives team domain from worker URL)
|
|
198
|
+
* Probe 3: POST /v1/oauth/start → endpoint reachability
|
|
199
|
+
* Probe 4: ANTHROPIC_OAUTH_CLIENT_ID env present (config check)
|
|
200
|
+
*/
|
|
201
|
+
export async function runDoctorChecks(opts) {
|
|
202
|
+
const results = [];
|
|
203
|
+
const { baseUrl, cfAuthCookie, fetchFn = fetch } = opts;
|
|
204
|
+
const base = normalizeBase(baseUrl);
|
|
205
|
+
// Probe 1: /v1/health
|
|
206
|
+
try {
|
|
207
|
+
const h = await remoteHealth({ baseUrl, cfAuthCookie, fetchFn });
|
|
208
|
+
results.push({
|
|
209
|
+
probe: 'worker-health',
|
|
210
|
+
status: 'pass',
|
|
211
|
+
message: `Worker alive${h.version ? ` (version=${h.version})` : ''}`,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
results.push({
|
|
216
|
+
probe: 'worker-health',
|
|
217
|
+
status: 'fail',
|
|
218
|
+
message: err instanceof Error ? err.message : 'Health check failed',
|
|
219
|
+
remedy: `Verify the worker is deployed and reachable at ${base}`,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// Probe 2: CF Access JWKS
|
|
223
|
+
// Extract team domain from the worker URL host segment.
|
|
224
|
+
// e.g. https://auth.example.workers.dev → team = "example"
|
|
225
|
+
// For custom domains like auth.myteam.example.com, we look for the last
|
|
226
|
+
// two segments of the authority. In practice workers.dev domains expose team name.
|
|
227
|
+
let jwksUrl;
|
|
228
|
+
try {
|
|
229
|
+
const parsed = new URL(baseUrl);
|
|
230
|
+
// heuristic: take the second-to-last part of the hostname before TLD pair
|
|
231
|
+
const parts = parsed.hostname.split('.');
|
|
232
|
+
// e.g. auth.myteam.cloudflareaccess.com or myteam.cloudflareaccess.com
|
|
233
|
+
// Best-effort: use the host as the team domain search key
|
|
234
|
+
const team = parts.length >= 3 ? parts[parts.length - 3] : parts[0];
|
|
235
|
+
jwksUrl = `https://${team}.cloudflareaccess.com/cdn-cgi/access/certs`;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
jwksUrl = `${base}/.well-known/jwks.json`;
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
const res = await fetchFn(jwksUrl, { method: 'GET' });
|
|
242
|
+
if (res.ok) {
|
|
243
|
+
results.push({
|
|
244
|
+
probe: 'cf-access-jwks',
|
|
245
|
+
status: 'pass',
|
|
246
|
+
message: `CF Access JWKS reachable at ${jwksUrl}`,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
results.push({
|
|
251
|
+
probe: 'cf-access-jwks',
|
|
252
|
+
status: 'warn',
|
|
253
|
+
message: `CF Access JWKS returned HTTP ${res.status}`,
|
|
254
|
+
remedy: `Verify Cloudflare Access is configured for your zone. JWKS checked: ${jwksUrl}`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
results.push({
|
|
260
|
+
probe: 'cf-access-jwks',
|
|
261
|
+
status: 'warn',
|
|
262
|
+
message: `CF Access JWKS unreachable: ${err instanceof Error ? err.message : String(err)}`,
|
|
263
|
+
remedy: `Check network access to ${jwksUrl}. CF Access may not be configured for this zone.`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// Probe 3: POST /v1/oauth/start
|
|
267
|
+
try {
|
|
268
|
+
await remoteOAuthStart({ baseUrl, cfAuthCookie, fetchFn });
|
|
269
|
+
results.push({
|
|
270
|
+
probe: 'oauth-start',
|
|
271
|
+
status: 'pass',
|
|
272
|
+
message: 'OAuth start endpoint is reachable',
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
277
|
+
// 403 means CF Access is enforcing SSO but the endpoint exists — that's a warn.
|
|
278
|
+
const status = msg.includes('HTTP 403') ? 'warn' : 'fail';
|
|
279
|
+
results.push({
|
|
280
|
+
probe: 'oauth-start',
|
|
281
|
+
status,
|
|
282
|
+
message: `OAuth start: ${msg}`,
|
|
283
|
+
remedy: status === 'warn'
|
|
284
|
+
? 'Open the worker URL in a browser to complete CF Access SSO, then re-run with --cookie.'
|
|
285
|
+
: `Check that /v1/oauth/start is deployed at ${base}`,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
// Probe 4: ANTHROPIC_OAUTH_CLIENT_ID env
|
|
289
|
+
const clientId = process.env['ANTHROPIC_OAUTH_CLIENT_ID'];
|
|
290
|
+
if (clientId) {
|
|
291
|
+
results.push({
|
|
292
|
+
probe: 'env-client-id',
|
|
293
|
+
status: 'pass',
|
|
294
|
+
message: `ANTHROPIC_OAUTH_CLIENT_ID is set (length=${clientId.length})`,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
results.push({
|
|
299
|
+
probe: 'env-client-id',
|
|
300
|
+
status: 'warn',
|
|
301
|
+
message: 'ANTHROPIC_OAUTH_CLIENT_ID is not set in the environment',
|
|
302
|
+
remedy: 'Set ANTHROPIC_OAUTH_CLIENT_ID in your shell profile (the Anthropic OAuth app client ID).',
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return results;
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=auth-remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-remote.js","sourceRoot":"","sources":["../../src/lib/auth-remote.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0DH,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,MAAe;IACnC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,kBAAkB;KAC3B,CAAC;IACF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,QAAQ,CAAC,GAAG,oBAAoB,MAAM,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAyB;IAEzB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAA6B,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAyB;IAEzB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,iBAAiB,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;QACnC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;KACzB,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAiC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAAyB;IAEzB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,oBAAoB,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAA6B,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAyB;IAEzB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,cAAc,CAAC;IACpD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAA6B,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAyB,EACzB,OAA6C;IAE7C,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,yBAAyB,CAAC;IAC/D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;QACnC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,IAAyB,EACzB,QAAgB;IAEhB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,sBAAsB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC1F,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,IAAyB,EACzB,KAAa;IAEb,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,4BAA4B,CAAC;IAClE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;QACnC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;KAChC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAA0C,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,IAAyB;IAEzB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,sBAAsB,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAoC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,IAAyB,EACzB,SAAiB;IAEjB,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,wBAAwB,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;IAC7F,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAyB;IAEzB,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IACxD,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAEpC,sBAAsB;IACtB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;SACrE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB;YACnE,MAAM,EAAE,kDAAkD,IAAI,EAAE;SACjE,CAAC,CAAC;IACL,CAAC;IAED,0BAA0B;IAC1B,wDAAwD;IACxD,2DAA2D;IAC3D,wEAAwE;IACxE,mFAAmF;IACnF,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,0EAA0E;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,uEAAuE;QACvE,0DAA0D;QAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,GAAG,WAAW,IAAI,4CAA4C,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,GAAG,IAAI,wBAAwB,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,gBAAgB;gBACvB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,+BAA+B,OAAO,EAAE;aAClD,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,gBAAgB;gBACvB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,gCAAgC,GAAG,CAAC,MAAM,EAAE;gBACrD,MAAM,EAAE,uEAAuE,OAAO,EAAE;aACzF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,gBAAgB;YACvB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YAC1F,MAAM,EAAE,2BAA2B,OAAO,kDAAkD;SAC7F,CAAC,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,IAAI,CAAC;QACH,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,aAAa;YACpB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,mCAAmC;SAC7C,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,gFAAgF;QAChF,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,aAAa;YACpB,MAAM;YACN,OAAO,EAAE,gBAAgB,GAAG,EAAE;YAC9B,MAAM,EACJ,MAAM,KAAK,MAAM;gBACf,CAAC,CAAC,wFAAwF;gBAC1F,CAAC,CAAC,6CAA6C,IAAI,EAAE;SAC1D,CAAC,CAAC;IACL,CAAC;IAED,yCAAyC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAC1D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,4CAA4C,QAAQ,CAAC,MAAM,GAAG;SACxE,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,yDAAyD;YAClE,MAAM,EACJ,0FAA0F;SAC7F,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|