( name: string, hostname: string, allowedEmails: readonly string[], )
| 158 | * unauthenticated /mcp requests get a browser login redirect instead. |
| 159 | */ |
| 160 | const ensureAccessApp = async ( |
| 161 | name: string, |
| 162 | hostname: string, |
| 163 | allowedEmails: readonly string[], |
| 164 | ): Promise<{ id: string; aud: string }> => { |
| 165 | const existing = await findAccessApp(name); |
| 166 | if (existing) { |
| 167 | process.stderr.write(`reusing Access app ${name} (aud ${existing.aud.slice(0, 8)}…)\n`); |
| 168 | return { id: existing.id, aud: existing.aud }; |
| 169 | } |
| 170 | const app = await cfOk("POST", `/accounts/${ACCOUNT}/access/apps`, { |
| 171 | name, |
| 172 | type: "self_hosted", |
| 173 | domain: hostname, |
| 174 | session_duration: "24h", |
| 175 | oauth_configuration: { |
| 176 | enabled: true, |
| 177 | grant: { session_duration: "24h", access_token_lifetime: "15m" }, |
| 178 | dynamic_client_registration: { |
| 179 | enabled: true, |
| 180 | allowed_uris: [], |
| 181 | allow_any_on_localhost: true, |
| 182 | allow_any_on_loopback: true, |
| 183 | }, |
| 184 | }, |
| 185 | }); |
| 186 | await cfOk("POST", `/accounts/${ACCOUNT}/access/apps/${app.id}/policies`, { |
| 187 | name: `${name}-allowed-emails`, |
| 188 | decision: "allow", |
| 189 | include: allowedEmails.map((email) => ({ email: { email } })), |
| 190 | }); |
| 191 | process.stderr.write(`created Access app ${name} for ${hostname}\n`); |
| 192 | return { id: app.id, aud: app.aud }; |
| 193 | }; |
| 194 | |
| 195 | /** |
| 196 | * Derive the preview wrangler config from the committed one (same bindings, |
no test coverage detected