Revised plan: do exactly what the generator of our mapping tool does, but automate the login/session collection, mapping, testing, and CLIProxyAPI upload. No OAuth PKCE scope expansion.
Automate login → open https://chatgpt.com/api/auth/session → collect session JSON/dump → run the generator mapper logic → upload JSON file.
Do not redesign scope around OpenAI OAuth PKCE or require refresh-token durability unless Kacher asks later.
The tool UI has settings for base_url and management key; upload code only calls the endpoint.
| Phase | Status | Current artifact | Next action |
|---|---|---|---|
| Phase 1 — UI first | In progress | projects/codex-auth-bulk-tool/public/index.html | Kacher review UI scaffold, then iterate styling/fields. |
| Phase 2 — Auth generator extraction | Started | src/auth-generator.mjs | Add fixtures/tests from real sanitized dump shape. |
| Phase 3 — CloakBrowser login | Pending | Not started | Implement after UI approval. |
| Phase 4 — Upload/test | Client scaffolded | src/cliproxy-client.mjs | Wire UI action + test endpoint behavior. |
The UI says: paste or collect a single sensitive dump containing fields like WARNING_BANNER, accessToken, and sessionToken. The parser is forgiving: it strips code fences, extracts the first JSON object, normalizes smart quotes, and removes trailing commas.
// parseLooseJson() behavior
normalize smart quotes / NBSP
strip ```json fences
slice first { ... last }
JSON.parse(), retry after removing trailing commas
The output is a clean JSON object with the old CLIProxyAPI Codex auth-file shape. Missing values are filled as __MISSING__ and highlighted yellow in the preview.
{
"access_token": "...",
"account_id": "...",
"disabled": false,
"email": "...",
"expired": "...",
"id_token": "__MISSING__",
"last_refresh": "...",
"refresh_token": "__MISSING__",
"type": "codex"
}
| Output auth field | Source in dump | Fallback / behavior |
|---|---|---|
access_token | dump.accessToken | If empty/missing → __MISSING__ and mark missing. |
account_id | dump.account.id | If empty/missing → __MISSING__. |
disabled | Not read from dump | Always false, because the generator assumes a usable account. |
email | dump.user.email or dump.account.email | If both missing → __MISSING__. |
expired | dump.expires | If missing → __MISSING__. |
id_token | dump.idToken or dump.id_token | sessionToken is not treated as id_token. Missing is surfaced. |
last_refresh | dump.last_refresh or dump.exported_at | If missing → __MISSING__. |
refresh_token | dump.refreshToken or dump.refresh_token | sessionToken is not treated as refresh_token. Missing is surfaced. |
type | Constant | Always codex. |
The generator download uses safeFileNameFromAuth():
codex-<sanitized email>-plus.json // sanitize rule String(auth.email || 'auth') .replace(/^<mailto:([^|>]+)\|([^>]+)>$/, '$2') .replace(/[^a-zA-Z0-9@._-]+/g, '_')
https://chatgpt.com/api/auth/session inside the authenticated context.sessionToken as id_token/refresh_token.base_url and management key to upload the generated file to CLIProxyAPI.| Topic | Source evidence | Decision |
|---|---|---|
| Existing mapper behavior | object-token-mapper-page/index.html the generator implements buildFromSensitiveDumpObject(). It maps dump fields such as accessToken, account.id, user.email, expires, idToken, refreshToken into the output auth JSON. | Reuse this logic as the core mapper library. |
| Upload endpoint | CLIProxyAPI/internal/api/server.go registers POST /v0/management/auth-files. internal/api/handlers/management/auth_files.go implements UploadAuthFile(). | Use endpoint directly; no browser upload click needed. |
| Upload payload | Cli-Proxy-API-Management-Center/src/services/api/authFiles.ts appends files via FormData field file. | Tool uploads multipart files using field name file. |
| Management settings | src/services/api/client.ts computes base_url + /v0/management and sends Authorization: Bearer <managementKey>. | UI settings must expose base_url and management key. |
| Testing uploaded files | /v0/management/api-call supports auth_index and $TOKEN$ replacement; quota code calls https://chatgpt.com/backend-api/wham/usage. | After upload, list auth files, get auth_index, test via API-call or configured test endpoint. |
base_urlusername | password | TOTP secretbase_url and management key in the tool settings. Store locally only if user explicitly enables encrypted save.username | password | TOTP secret. Validate that the third field is a TOTP secret; never accept pre-generated 6-digit codes and never echo secrets.https://chatgpt.com/api/auth/session inside the authenticated browser context.__MISSING__ and are surfaced exactly like the generator preview, not silently invented./api-call depending on available output fields. Mark pass/fail with clear reason.{base_url}/v0/management/auth-files using the configured management key.Field 3 is always a TOTP secret. The tool uses a standard TOTP library such as otplib to generate the current 6-digit confirmation code automatically.
import { authenticator } from 'otplib';
const code = authenticator.generate(secret);There is no supported case for pre-entered 6-digit codes or manual prompts. If the TOTP secret is missing/invalid and ChatGPT asks for 2FA, the row fails with a clear error.
email | password | JBSWY3DPEHPK3PXP # invalid: email | password | 123456 # invalid: email | password |
| Area | Cleanup action | Why |
|---|---|---|
| Browser context | Close page/context after each account. | Prevents account cross-contamination. |
| Cookies/storage | Clear cookies, localStorage, sessionStorage, IndexedDB/cache where supported. | Removes ChatGPT session state. |
| Temporary profile | Use a per-account temp CloakBrowser profile and delete the directory after run. | Reduces browser fingerprint/session residue. |
| Auth JSON temp file | Write with 0600, upload, then delete unless --keep-files. | Limits token exposure on disk. |
| Logs/report | Redact password, 2FA secret, access tokens, session JSON. | Operator can debug without leaking credentials. |
| Phase | Scope | Deliverable | Exit criteria |
|---|---|---|---|
| Phase 1 | UI first | Standalone local HTML design with settings, account input, progress table, report export, and clear status taxonomy. | Kacher approves UX before engine work. |
| Phase 2 | Auth generator extraction | Shared JS library for Session Dump → Auth JSON: parse session dump → auth JSON + missing-field report. | Given the same dump, output matches the current generator logic. |
| Phase 3 | CloakBrowser login prototype | Single-account login, TOTP-secret-only 2FA handling, fetch /api/auth/session, cleanup footprint. | One account runs end-to-end without retaining session residue. |
| Phase 4 | Upload/test integration | Settings-based CLIProxyAPI uploader and test runner. | Generated file uploads through endpoint and appears in Auth Files. |
| Phase 5 | Batch workflow | Serial queue, retry rules, fail-fast on missing/invalid TOTP secret, redacted report. | Batch handles mixed success/failure safely. |
| Phase 6 | Packaging & docs | README, install script, examples, troubleshooting guide, optional AppleScript fallback note. | Repeatable run on Kacher’s machine. |
/api/auth/session# Upload generated auth file using tool settings curl -sS -X POST "$BASE_URL/v0/management/auth-files" \ -H "Authorization: Bearer $MANAGEMENT_KEY" \ -F "file=@generated-auth.json;type=application/json" # Raw JSON alternative curl -sS -X POST "$BASE_URL/v0/management/auth-files?name=generated-auth.json" \ -H "Authorization: Bearer $MANAGEMENT_KEY" \ -H "Content-Type: application/json" \ --data-binary @generated-auth.json