Skip to content

auth status reports 'session cached' for any file at the cache path — doesn't validate the cached session is usable #46

Description

@DTTerastar

cmd/auth.go::authStatusCmd reports the cache state with a bare os.Stat:

if p := exporter.SessionCachePath(); p != "" {
    if _, err := os.Stat(p); err == nil {
        cacheState = "session cached"
    } else {
        cacheState = "no session cached"
    }
}

But exporter.loadCachedSession(user) — the function the export commands actually call to load the cache — performs four additional checks the status command skips:

  1. JSON parses
  2. Version == cacheSchemaVersion (so a stale-schema cache from an old binary doesn't get used)
  3. Username == user (so switching CRONOMETER_USERNAME invalidates the cache)
  4. AuthToken != "" (so a zero/truncated file is rejected)

Any cache that passes os.Stat but fails one of those four is reported by auth status as session cached — and then the very next crono-export nutrition call silently re-logs in because the load actually fails. The status message lies.

The contract §5 expects auth status to be a useful readiness signal ("logged in as you@example.com (token expires 2026-05-01)" / "missing CRONOMETER_PASSWORD"). "I see a file at the path" doesn't clear that bar.

Easy fix

Swap the os.Stat for a call to loadCachedSession. The function already exists and does exactly the right validation; only thing it needs is to become exported (or a thin wrapper). Then the three branches become:

  • (valid cached session) — file present, parses, version + user + token all good
  • (no usable cached session) — file absent, or present-but-rejected
  • (cache disabled (CRONOMETER_NO_CACHE set)) — unchanged

No network call, so still satisfies the "local-only" promise.

Also stale

The command's Long description still claims:

This is a local check — no network call. It only verifies the
CRONOMETER_USERNAME and CRONOMETER_PASSWORD environment variables are set.

The function now also checks the cache path. Update the Long to match.

Severity: minor (correctness of an advisory subcommand)

Activity

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

    area:authauth status / auth login / env-var auth surface.kind:bugObserved behavior diverges from documented behavior.priority:mediumReproducible bug or gap with a workaround, or a well-scoped enhancement clearly in charter.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions