6.9 KiB
GitOps Write Auth Fix Acceptance
Time: 2026-07-06T13:26:26Z
Branch: patch/gitops-write-auth-fix
Patch commit: see git rev-parse --short patch/gitops-write-auth-fix
Bridge GPT: codex-chartgpt-bridge
Bridge URL: https://chatgpt.com/g/g-6a4ba1b4ea588191bab125d53ce83612-codex-chartgpt-bridge
Result
SERVER-SIDE PASS. The GitOps API write path accepts valid Bearer tokens and rejects no-token writes. The external GPT still must have Bearer authentication configured in GPT Builder Actions; a GPT URL alone cannot inject the header.
Root Cause Confirmed
- Read endpoints were healthy without auth.
- Write endpoints returned
401 unauthorizedwhen Actions did not sendAuthorization: Bearer .... - Runtime token registry supports write scopes; the broken boundary was Actions auth header injection / write token binding.
Fix Applied
- Added dedicated runtime account
gitops-write-bot. - Runtime token file:
/data/aios-gitops/runtime/secrets/gitops-write-bot.token, mode600. - Token registry stores hash/scopes only in
/data/aios-gitops/runtime/secrets/gitops.tokens. - Git-visible token reference only:
secret_ref://aios-gitops/runtime/gitops-write-bot. - OpenAPI now advertises Bearer auth, write operation scopes, and the bridge GPT URL.
/api/statusreturnsbridge_gptswith thecodex-chartgpt-bridgeURL and auth-binding status.- Added bridge setup doc:
docs/gitops/CODEX_CHATGPT_BRIDGE_ACTIONS_SETUP.md. - Added smoke script:
scripts/smoke_gitops_write_auth.py.
Smoke Results
gitops-write-bot
{
"noauth": {"operation": "createPatch without token", "http": 401, "status": "unauthorized"},
"createPatch": {"operation": "createPatch", "http": 200, "status": "patch_branch_created", "branch": "patch/gitops-write-auth-smoke-20260706T115230Z", "rev": "6d3a050", "sync_status": "synced"},
"commitFile": {"operation": "commitFile", "http": 200, "status": "committed", "branch": "patch/gitops-write-auth-smoke-20260706T115230Z", "rev": "17344f7", "sync_status": "synced"}
}
codex-gitops-bot
{
"noauth": {"operation": "createPatch without token", "http": 401, "status": "unauthorized"},
"createPatch": {"operation": "createPatch", "http": 200, "status": "patch_branch_created", "branch": "patch/codex-write-auth-smoke-20260706T115256Z", "rev": "d684df2", "sync_status": "synced"},
"commitFile": {"operation": "commitFile", "http": 200, "status": "committed", "branch": "patch/codex-write-auth-smoke-20260706T115256Z", "rev": "884a5ec", "sync_status": "synced"}
}
codex-chartgpt-bridge binding smoke
{
"noauth": {"operation": "createPatch without token", "http": 401, "status": "unauthorized"},
"createPatch": {"operation": "createPatch", "http": 200, "status": "patch_branch_created", "branch": "patch/bridge-write-auth-smoke-20260706T132506Z", "rev": "f4ef8e5", "sync_status": "synced"},
"commitFile": {"operation": "commitFile", "http": 200, "status": "committed", "branch": "patch/bridge-write-auth-smoke-20260706T132506Z", "rev": "0ed0816", "sync_status": "synced"}
}
ClientResponseError Retest (2026-07-06T13:47:06Z)
The external GPT Actions failure was reproduced as a write-auth boundary issue, not a public endpoint outage. Public reads reached the API and returned typed responses, while writes without a valid Bearer credential returned structured 401 responses.
GET /api/base: 200 application/json
GET /api/run: 200 application/json
GET /api/status: 200 application/json
GET /api/openapi-chatgpt-actions.yaml: 200 application/yaml
POST /api/patch without token: 401 auth_state=missing_bearer
POST /api/patch with literal secret_ref as token: 401 auth_state=secret_ref_literal_not_token
POST /api/patch with duplicated Bearer prefix: 200 branch=patch/actions-double-bearer-20260706T134646Z rev=ddd8711 sync_status=synced
POST /api/patch with raw runtime token: 200 branch=patch/actions-raw-token-smoke-20260706T134706Z rev=0e48e1d sync_status=synced
POST /api/file with raw runtime token: 200 branch=patch/actions-raw-token-smoke-20260706T134706Z rev=6ab67e9 sync_status=synced
Server-side compatibility added in this patch:
- Normalize accidental
Authorization:and repeatedBearerprefixes before token verification. - Reject literal
secret_ref://...as a token and returnauth_state=secret_ref_literal_not_token. - Return
auth_state,required_scope, and GPT Builder guidance on401. - Return top-level
branch,rev, andsync_statuson write success so Actions can make deterministic pass/fail decisions. - Support
HEADprobes for public read/schema endpoints so GPT Builder or gateway validators do not see501during endpoint discovery.
GPT Builder still must store the raw runtime token in the hidden API key field. The public secret_ref://aios-gitops/runtime/gitops-write-bot value is a pointer only and must not be used as the API key.
HEAD compatibility retest:
HEAD /api/base: 200 application/json
HEAD /api/run: 200 application/json
HEAD /api/openapi-chatgpt-actions.yaml: 200 application/yaml
External GPT Retest (2026-07-06T13:59:43Z)
The custom GPT retest reached the server:
GET /api/run: 200
GET /api/base: 200
POST /api/branch: 401
POST /api/patch: 401
This confirms that routing, TLS, schema loading, and read access are healthy. The remaining failure is the external GPT Builder secret binding: the write request does not carry the runtime gitops-write-bot raw token value. If a token-like value is present but does not match the token registry, the API now reports auth_state=invalid_token and rebind_required=true.
External GPT Builder Binding Required
Configure the GPT Actions auth for codex-chartgpt-bridge as:
Schema URL: https://cnnetmkt.top/api/openapi-chatgpt-actions.yaml
Authentication type: API Key / Bearer
Header: Authorization
Value / API key field: <raw runtime token value only>
Secret source: secret_ref://aios-gitops/runtime/gitops-write-bot
The actual token value must be read from /data/aios-gitops/runtime/secrets/gitops-write-bot.token and entered only into the GPT Builder secret/auth field. Do not paste it into chat or Git.
Exit Criteria
- ChatGPT Actions write capability: PASS once the GPT Builder auth field is bound to the runtime token.
- Server-side authenticated write path: PASS.
- Codex API commit capability: PASS.
- No-token write requests remain rejected: PASS,
401 unauthorized. - No plaintext token committed to Git: PASS by workspace secret pattern scan.
Security Notes
The patch does not allow direct main writes, does not permit tag deletion, and does not bypass owner/admin approval for V-level actions. Credentials stay in runtime secrets; Git stores only secret refs and token hashes.
Important: because the GPT Builder screenshot has Bearer selected, the API key field must contain only the raw token value. Do not type Bearer in that field. Do not type secret_ref://aios-gitops/runtime/gitops-write-bot; that string is a public reference, not a credential.