Files
aios/docs/gitops/GITOPS_WRITE_AUTH_FIX_ACCEPTANCE.md
T
2026-07-06 22:02:45 +08:00

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 unauthorized when Actions did not send Authorization: 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, mode 600.
  • 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/status returns bridge_gpts with the codex-chartgpt-bridge URL 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 repeated Bearer prefixes before token verification.
  • Reject literal secret_ref://... as a token and return auth_state=secret_ref_literal_not_token.
  • Return auth_state, required_scope, and GPT Builder guidance on 401.
  • Return top-level branch, rev, and sync_status on write success so Actions can make deterministic pass/fail decisions.
  • Support HEAD probes for public read/schema endpoints so GPT Builder or gateway validators do not see 501 during 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.