Skip to content

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

@DTTerastar

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)

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions