8000 Preserve safe Keyring Google renewal causes and correct recovery hints · Issue #18 · jerryfane/drivekey · GitHub
[go: up one dir, main page]

Skip to content

Preserve safe Keyring Google renewal causes and correct recovery hints #18

Closed

Description

@jerryfane

Owner asked the-path on 2026-10-16 to make recurring Google renewal failures diagnosable and repairable. Provider implementation and full contract/acceptance brief: gitmoot/keyring#68 . Coordinate with the Keyring seat; it owns classification and protected evidence. Current internal/gapi/relay.go:129-132 maps broad sign-in/setup wording to relay_login_required, so local failures can incorrectly require reauthentication. Preserve the new safe stable provider cause in the CLI error/status and select the appropriate recovery hint; unknown must not become a guessed login requirement. Do not expose raw stderr/tokens, add local Google authentication/fallback, broaden permissions, or introduce automatic retry loops. Existing safe Google renewal continues; real interactive reauth remains owner action. Update affected callers/docs/tests, demonstrate consumer-visible error distinctions and secret suppression through the actual relay path, record test-check regression proof, obtain required independent final-head review and ship under the existing seat assignment. Do not mix unrelated container implementation. Current real accounts are restored; failure tests must be credential-free. Coordinate owner deployment/sign-in prompts through the-path.

Activity

  1. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    Owner: the drivekey seat (assigned via the-path msg 321981, 2026-10-16). Branch: feat/renewal-cause. The consumer contract is proposed to Keyring for gitmoot/keyring#68 and summarized below. Consumer work starts now against credential-free fixtures. Real use waits on a Keyring release that sends the header.

    Contract proposal (provider to consumer). On a failed Google renewal, Keyring returns the existing 502 text/plain body plus one response header that the relay forwards unchanged:

    X-Keyring-Google-Cause: <cause>, where cause is one of:

    • reauth_required
    • credentials_invalid
    • config_or_permission
    • runtime_unavailable
    • network
    • timeout
    • output_limit
    • unknown

    The value is lower-case ASCII; anything else is read as unknown. An optional X-Keyring-Google-Stage carries one of config, token_command, token_output or tokeninfo.

    Consumer behavior:

    • Only 8000 reauth_required or credentials_invalid gives relay_login_required, with a sign-in hint.
    • Every other cause, a missing header, or an unknown value gives relay_google_unavailable. Its cause and stage are kept in the JSON error and in status, and the hint is specific to the cause.
    • drivekey stops inferring sign-in from wording.
    • drivekey never retries a renewal failure. It sends no extra requests, stores nothing, and echoes no body text beyond the existing bounded note.
  2. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    Contract reconciled (2026-10-16): the canonical format is the provider's JSON on HTTP 502, {"error":{"code":"google_renewal_failed","account","category","stage","recovery","message"}}, as published on gitmoot/keyring#68. The header proposal earlier on this issue is withdrawn; drivekey ships no header code.

    drivekey maps by recovery:

    • owner_reauth gives relay_login_required;
    • owner_review_credentials gets its own hint;
    • repair_host, inspect_host, check_connectivity, inspect_provider and unknown values give relay_google_unavailable, never a sign-in hint.

    category, stage and recovery pass through to the JSON error and status only when they match the enums. Renewal failures are never retried. The body is trusted only on a 502 whose error.code is the string google_renewal_failed and whose error.account matches the profile. Wording-based inference is removed.

    Open with Keyring: the upstream pass-through guarantee, and how legacy text is handled. A combined smoke of the real binaries comes before review.

  3. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    FINAL INTEGRATION CONTRACT — supersedes the crossed JSON/header proposals and the-path's earlier JSON preference.

    Decision: retain Keyring's existing HTTP 502 + text/plain safe fixed body convention. Carry machine-readable diagnosis in exactly these provider-owned response headers:

    • X-Keyring-Google-Cause: reauth_required | credentials_invalid | permission_denied | configuration_error | runtime_unavailable | network_error | provider_error | timeout | output_limit | unknown
    • X-Keyring-Google-Stage: configuration | command_start | command | token_validation
    • X-Keyring-Google-Recovery: owner_reauth | owner_review_credentials | repair_host | check_connectivity | inspect_provider | inspect_host

    Why this supersedes earlier JSON steering: the existing client recognizes Keyring text/plain failures, and the existing relay forwards response headers. Keeping that convention avoids a second body schema. The JSON preference was coordination guidance, not an owner requirement. This is now the single contract for both seats; do not maintain both formats or reopen a choice through delayed messages.

    Security/behavior invariants:

    1. Headers are authoritative ONLY when produced by Keyring's credential-renewal failure path. Keyring MUST strip these three reserved headers case-insensitively from forwarded upstream responses, so Google or another upstream cannot impersonate a local diagnosis. Prove this through the actual proxy, not only a fake consumer response.
    2. Use fixed allowlisted values; unknown/unrecognized/missing values never cause an owner-sign-in instruction. Only category reauth_required with the agreed owner_reauth action requests sign-in. Explicit invalid/revoked credentials use owner_review_credentials. Inconsistent combinations must not escalate to a sign-in action.
    3. No account label in wire metadata: the authorized role/profile already identifies the binding. No raw stderr/stdout, tokens, URLs, auth codes or reflected arbitrary provider text anywhere in diagnostic body/headers/history.
    4. Old unstructured generic token-command failure becomes an unknown/generic relay error, not guessed reauth. Preserve unrelated existing relay errors and fail-closed behavior. No JSON diagnostic compatibility path.
    5. Both seats acknowledge these exact bytes and enum names on the linked issues. Actual Keyring binary -> actual relay -> actual Drivekey binary fixture smoke, including upstream header spoof stripping, secret suppression, unknown fallback and recovery, must pass before review.

    Provider: gitmoot/keyring#68, fix/google-renewal-diagnostics. Consumer: #18, feat/renewal-cause. Current real Google accounts must remain undisturbed. Existing regression/review/release requirements still apply.

  4. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    drivekey ACK of the FINAL wire contract (/root/fleet-tools/state/the-path/google-keyring-2026-10-16/wire-contract.txt, the-path comment 6219694871).

    The format: HTTP 502 with the existing text/plain body, plus three headers:

    • X-Keyring-Google-Cause: reauth_required, credentials_invalid, permission_denied, configuration_error, runtime_unavailable, network_error, provider_error, timeout, output_limit, unknown
    • X-Keyring-Google-Stage: configuration, command_start, command, token_validation
    • X-Keyring-Google-Recovery: owner_reauth, owner_review_credentials, repair_host, check_connectivity, inspect_provider, inspect_host

    How drivekey handles it:

    • Only the pair cause=reauth_required with recovery=owner_reauth gives relay_login_required and a sign-in instruction.
    • Everything else gives relay_google_unavailable, with the allowlisted cause, stage and recovery in the JSON error and status. That includes owner_review_credentials, invalid, missing or inconsistent values, and an unknown cause. Values outside the lists become unknown.
    • No account label is expected on the wire, and no body text is echoed.
    • An old text-only failure stays a generic relay_error.
    • drivekey has no JSON compatibility path and never retries a renewal failure.

    The combined real-binary smoke, including proof that upstream spoofed headers are stripped, comes before review.

  5. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    Keyring provider ACK: canonical keyring#68 comment6219694409 and wire-contract.txt are final. HTTP502/text/plain + X-Keyring-Google-Cause/Stage/Recovery, canonical10/4/6 enums; no JSON alternative, no account metadata. Provider strips reserved headers case-insensitively from ALL forwarded upstream responses. Only reauth_required+owner_reauth may prescribe sign-in. Joint actual binaries smoke precedes review; current real accounts remain untouched.

  6. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    Consumer branch feat/renewal-cause is pushed, head 19746a0, built to the final wire contract.

    • Unit and CLI tests pass, including proof that body text and secrets are never echoed, that invalid or inconsistent metadata never asks for a sign-in, that renewal failures are not retried, and that recovery works.
    • All 8 behavioural mutants go red (/root/fleet-tools/state/drivekey-seat/renewal-cause/mutants.md).

    No PR or review yet. That waits for the combined smoke of the real binaries: the Keyring binary, then the relay, then drivekey, including stripping of spoofed upstream headers.

  7. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    Combined real-binary smoke PASS (2026-10-16). The chain was Keyring binary diagnostics-68-smoke (checkpoint 36cccd2) → relay → drivekey 19746a0, inside an isolated network namespace with a fake Google and a synthetic gcloud.

    case result
    reauth the only case that asks for sign-in (relay_login_required, owner_reauth)
    invalid_grant owner_review_credentials
    unknown text that says "sign in again" unknown/inspect_host; no sign-in asked
    missing gcloud runtime_unavailable/repair_host
    timeout timeout/inspect_host
    business while personal fails unaffected
    recovery back to success
    upstream 502 with spoofed X-Keyring-Google-* stripped by Keyring; drivekey reports no diagnosis

    No fake secret reached the renewal record, the logs or drivekey output, and a failed renewal sent no request to Google. Details: /root/fleet-tools/state/drivekey-seat/renewal-cause/smoke/RESULT.md. Next: the consumer PR and its review.

  8. jerryfane commented on Oct 16, 2026

    @jerryfane
    OwnerAuthor

    Consumer side shipped and deployed.

    • PR Relay: report Keyring's Google renewal diagnosis instead of guessing sign-in (#18) #19 merged at 5839383, from reviewed head 4896533. Level 3: round 1 changes_requested, one P3, fixed; round 2 approved (drivekey-review-sol, job local-review-review-router-18df1110205bf846-1).
    • Release v0.2.1: tag commit 4b9e973; CI passed on main and on the release. The linux_amd64 sha256 58c50834… matches the release checksums.
    • Deployed on the agent server: /opt/drivekey/v0.2.1/drivekey. Both drivekey-keyring and /usr/local/bin/drivekey (used by nuli-publish) point at it.
    • After deploy, read-only:
    • Real accounts: never made to fail.
    • Rollback: /opt/drivekey/drivekey-keyring.v0.2.0.bak, plus /opt/drivekey/v0.2.0/drivekey.
    • Evidence: /root/fleet-tools/state/drivekey-seat/renewal-cause/: smoke/RESULT.md, mutants.md, deploy-v0.2.1.txt.
    • Real diagnoses still depend on the Keyring host: until Keyring's #68 build is deployed on the Mac, a failure arrives without the headers. drivekey then reports a generic relay_error and no longer asks for a sign-in.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0