Skip to content

feat: add an online-only Time & Bill CLI pilot - #94

Open
grobmeier wants to merge 22 commits into
mainfrom
feature/timeandbill-cli-pilot
Open

grobmeier wants to merge 22 commits into
mainfrom
feature/timeandbill-cli-pilot

Conversation

@grobmeier

@grobmeier grobmeier commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Add an explicit online-only remote CLI namespace for Time & Bill profiles, read commands, booking, conditional timers and mutation recovery, without changing local-first commands or uploading local databases.
  • Require the authenticated server safety contract, bounded TLS transport and no redirects; store credentials only in native secure storage or explicit ephemeral mode.
  • Journal mutation identifiers before dispatch, never auto-retry writes, and recover uncertain outcomes without replaying bookings.
  • Integrate current main dependency/toolchain updates. Fix the real servers successful stop/book response, which clears its reusable timer interval instead of leaving an end timestamp.

Verification

  • Complete Go and race suites, go vet and vulnerability scan pass under Go 1.26.10. Latest complete Go run: 172 passing tests/subtests plus one opt-in native-vault skip.
  • Real native-vault CI checks passed on Windows Credential Manager, macOS Keychain and an isolated Linux Secret Service session; the approved local macOS dummy-secret check also passed and removed its entry.
  • The companion server repository ran this native CLI against real loopback server JVMs and disposable fixture data: a dropped committed booking response was recovered after a literal server-process restart using a new CLI process, with exactly one manual entry and unchanged local database bytes.
  • That acceptance also covers Unicode/multiline notes, project/task reads, same-task start without reset, discard, booking a timer created through the web service, and fresh revoked-token denial. The stop-response mismatch failed before its Go fix and passed afterwards.
  • Keep final exact-head CI green, including existing browser tests and Linux/Windows/macOS GUI builds.

Hold / Release Gates

  • Keep this PR unmerged until the companion server integration merges after exact-head CI. The owner-approved migration renumbering is implemented and local upgrade/process acceptance passes; CI is waiting for its offline runner to recover.
  • Only local disposable server checks have been approved. They are not deployed staging/production acceptance; no server deployment or release has been performed.
  • Every serving server replica must support the safety contract before enabling a released client, and connected clients must be disabled before rolling back to legacy code.
  • Locked/denied desktop-vault prompts remain a manual check; native CI round-trips do not establish every desktop policy configuration.
  • GUI connected mode, offline queues/sync, remote project editing and local database upload remain out of scope.

See docs/connected-cli.md and docs/connected-cli-test-plan.md.

@grobmeier

Copy link
Copy Markdown
Owner Author

Reviewed current head 2425b29 on 2026-10-31. Existing Go, browser, security-analysis and Linux/Windows/macOS GUI checks are green. Keep this PR unmerged as agreed: the corresponding Time & Bill server safety contract is not yet integrated/deployed, and native credential-store plus authenticated staging/restart acceptance remain open. Once those gates are satisfied, integrate current main dependency/toolchain changes and rerun exact-head checks before reconsidering merge. No release or server deployment has been performed.

Use unique dummy entries on Windows/macOS and a disposable D-Bus Secret Service session on Linux.
The real server clears a successfully booked timer. Preserve exact-target and receipt checks while accepting its idle zero-duration state instead of reporting an uncertain write.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical flaws can expose credentials, treat uncertain bookings as definitively rejected or successful, and lose recovery journals after a power failure.

6 open issues
What changed in this PR

Adds an optional, online-only Time & Bill CLI alongside HumbleBee’s local-first workflows, without uploading or opening local databases.

Changes:

  • Introduces remote profiles, reads, bookings, timer controls and mutation recovery.
  • Adds authenticated safety-contract checks, secure credential storage and structured CLI output.
  • Adds automated coverage, native-vault CI and documentation separating local verification from deployment and release gates.
File Description
SECURITY.md Documents connected-client safety and reporting scope.
README.md Introduces the pilot and links its guides.
internal/​remotecli/​writes.go Defines booking, timer and recovery commands.
internal/​remotecli/​writes_test.go Tests booking arguments and Unicode JSON output.
internal/​remotecli/​output.go Formats results, diagnostics and recovery guidance.
internal/​remotecli/​command.go Registers remote commands and profile selection.
internal/​remotecli/​command_test.go Tests database isolation and account-local dates.
internal/​connected/​writes.go Implements booking validation and mutation recovery.
internal/​connected/​writes_test.go Tests journaling, lost responses and booking validation.
internal/​connected/​timers.go Implements conditional timer operations and cleared-stop responses.
internal/​connected/​timers_test.go Tests timer targets, reuse and booking intent.
internal/​connected/​reads.go Implements validated remote data reads.
internal/​connected/​reads_test.go Tests filtering, time units and note preservation.
internal/​connected/​profiles.go Manages profiles, account bindings and state files.
internal/​connected/​profiles_test.go Tests credential separation and profile safeguards.
internal/​connected/​operations.go Defines mutation receipts and recovery journals.
internal/​connected/​keyring.go Integrates native secure credential storage.
internal/​connected/​keyring_native_test.go Adds opt-in native-vault round-trip checks.
internal/​connected/​errors.go Defines safe errors and remote exit categories.
internal/​connected/​errors_test.go Tests server-error exit mappings.
internal/​connected/​client.go Adds authenticated, bounded transport without redirects.
internal/​connected/​client_test.go Tests transport and protocol safeguards.
internal/​connected/​capabilities.go Validates the server safety contract.
internal/​cli/​root.go Integrates remote commands and error handling.
internal/​cli/​root_test.go Tests local and remote exit classifications.
internal/​cli/​remote_process_test.go Tests cross-process recovery and database isolation.
go.sum Records credential-storage dependency checksums.
go.mod Adds keyring and terminal dependencies.
docs/​connected-cli.md Documents operation, recovery and scripting behavior.
docs/​connected-cli-test-plan.md Records verification procedures and release gates.
cmd/​humblebee/​main.go Preserves remote exit codes at process termination.
.github/​workflows/​test.yml Adds native-vault checks across supported platforms.

Review effort: Balanced

Comment on lines +159 to +160
failure := remoteError(code)
failure.definitive = true
if m.Resources.TimeUUID != "" && !validUUID(m.Resources.TimeUUID) || m.Resources.ProjectUUID != "" && !validUUID(m.Resources.ProjectUUID) || m.Resources.StopwatchID < 0 {
return false
}
return m.ErrorCode == "" || safeCode(m.ErrorCode)
Comment on lines +126 to +127
if err == nil {
err = os.Rename(f.Name(), path)
Comment on lines +161 to +163
if !validMutation(m, id, m.Operation) || a != nil && a.Operation != m.Operation {
return m, uncertain(id)
}
Comment on lines +63 to +65
func (s *Store) saveAttempt(a *Attempt) error {
return writePrivateJSON(filepath.Join(s.dir, "operations", a.MutationID+".json"), a)
}
Comment on lines +151 to +153
if err := s.Client.call(ctx, "get_mutation_status", map[string]any{"clientMutationId": id}, &response); err != nil {
return Mutation{}, err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants