Skip to content

feat: implement runtime and build time env variables for remote access#1316

Merged
Crunchyman-ralph merged 7 commits intonextfrom
ralph/feat/add.prod.hamster
Oct 16, 2025
Merged

feat: implement runtime and build time env variables for remote access#1316
Crunchyman-ralph merged 7 commits intonextfrom
ralph/feat/add.prod.hamster

Conversation

@Crunchyman-ralph
Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph commented Oct 16, 2025

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ralph Khreish 35776126+Crunchyman-ralph@users.noreply.github.com# What type of PR is this?

  • 🐛 Bug fix
  • ✨ Feature
  • 🔌 Integration
  • 📝 Docs
  • 🧹 Refactor
  • Other:

Description

Related Issues

How to Test This

# Example commands or steps

Expected result:

Contributor Checklist

  • Created changeset: npm run changeset
  • Tests pass: npm test
  • Format check passes: npm run format-check (or npm run format to fix)
  • Addressed CodeRabbit comments (if any)
  • Linked related issues (if any)
  • Manually tested the changes

Changelog Entry


For Maintainers

  • PR title follows conventional commits
  • Target branch correct
  • Labels added
  • Milestone assigned (if applicable)

Summary by CodeRabbit

  • New Features

    • Interactive search for selecting briefs during workspace setup.
    • Workspace context now auto-initializes after successful login.
    • Storage backends report their type ('api' / 'file').
  • Improvements

    • Briefs include document metadata (title) and display titles with IDs.
    • Environment variable precedence now favors runtime values for domains and services.
    • Export and API endpoint resolution updated to respect runtime/base domains.
    • CLI shows clearer messages when required service configuration is missing.
  • Bug Fixes

    • Suppresses repeated warnings for missing credential expirations.
  • Chore

    • Developer tooling loads environment variables earlier for correct runtime behavior.

@changeset-bot
Copy link

changeset-bot bot commented Oct 16, 2025

⚠️ No Changeset found

Latest commit: 22a6c79

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 16, 2025

Walkthrough

Prefer runtime TM_* environment variables over build-time TM_PUBLIC_* fallbacks; add interactive CLI post-login context setup with search-driven brief selection; enrich Briefs with document metadata; add storage getType() methods; suppress repeated credential-expiration warnings; defer dev CLI import until dotenv loads.

Changes

Cohort / File(s) Summary
Env var & config updates
packages/tm-core/src/auth/config.ts, packages/tm-core/src/clients/supabase-client.ts, packages/tm-core/src/services/export.service.ts, packages/tm-core/src/storage/storage-factory.ts, scripts/dev.js
Prefer runtime TM_* variables first (e.g., TM_BASE_DOMAIN, TM_SUPABASE_*) with TM_PUBLIC_* as fallback; update BASE_DOMAIN and DEFAULT_AUTH_CONFIG typing; expand supabase error wording to reference both runtime/build vars; compute export/api endpoints from runtime-first env; move dotenv.config() earlier and dynamically import dev CLI.
Interactive CLI & dependency
apps/cli/package.json, apps/cli/src/commands/auth.command.ts, apps/cli/src/commands/context.command.ts
Add @inquirer/search dependency; after successful interactive login invoke new ContextCommand.setupContextInteractive(); replace static brief prompt with search-enabled selection and prefer brief.document.title when available.
Organization / Brief enrichment
packages/tm-core/src/services/organization.service.ts
Add optional document object to Brief interface and populate brief.document (id, title, document_name, description?) from joined document fields in getBriefs/getBrief queries and mappings.
Storage type introspection
packages/tm-core/src/storage/api-storage.ts, packages/tm-core/src/storage/file-storage/file-storage.ts
Add public getType() methods returning literal 'api' and 'file' respectively.
Credential warning behavior
packages/tm-core/src/auth/credential-store.ts
Add instance flag hasWarnedAboutMissingExpiration to emit the missing-expiration warning only once per run; reset flag after successful save.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant CLI_Auth as apps/cli auth.command
    participant CLI_Context as apps/cli context.command
    participant OrgSvc as tm-core organization.service

    User->>CLI_Auth: start interactive login
    CLI_Auth->>CLI_Auth: performInteractiveAuth()
    CLI_Auth->>User: prompt & authenticate
    alt auth success
        CLI_Auth->>CLI_Context: setupContextInteractive()
        CLI_Context->>User: search/select organization
        User-->>CLI_Context: choose org
        CLI_Context->>OrgSvc: getBriefs(orgId)
        OrgSvc-->>CLI_Context: briefs (may include document metadata)
        CLI_Context->>User: search/select brief (or skip)
        User-->>CLI_Context: brief chosen / skip
        CLI_Context->>CLI_Auth: return setup result
        CLI_Auth->>User: login + context setup complete
    else auth failure
        CLI_Auth->>User: login failed
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The pull request title focuses solely on implementing runtime and build-time environment variables for remote access, but the changeset also includes extensive updates to CLI authentication workflows, interactive context setup with search prompts, enhancements to credential store warnings, storage type identification methods, and export logic branching. As such, the title does not capture the primary scope or the main features delivered in this PR. It is overly narrow and does not provide a clear summary of the overall changes made. Update the pull request title to reflect the full scope of the changes or split the PR into smaller, focused PRs. For example “feat(cli): add interactive context setup with search prompts” and “feat(core): support runtime/build-time environment variables for remote services”.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ralph/feat/add.prod.hamster

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2100fe4 and 22a6c79.

📒 Files selected for processing (1)
  • apps/cli/src/commands/auth.command.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/cli/src/commands/auth.command.ts (1)
apps/cli/src/commands/context.command.ts (1)
  • ContextCommand (32-785)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (1)
apps/cli/src/commands/auth.command.ts (1)

355-384: Post-auth context workflow looks robust.

Nice job wiring the interactive context setup straight into the auth success path, including partial-success messaging and guarded DEBUG logging. This makes the flow feel polished without risking auth regressions.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bc75c0 and 191a2fd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • apps/cli/package.json (1 hunks)
  • apps/cli/src/commands/auth.command.ts (2 hunks)
  • apps/cli/src/commands/context.command.ts (7 hunks)
  • packages/tm-core/src/auth/config.ts (1 hunks)
  • packages/tm-core/src/auth/credential-store.ts (3 hunks)
  • packages/tm-core/src/clients/supabase-client.ts (1 hunks)
  • packages/tm-core/src/services/export.service.ts (1 hunks)
  • packages/tm-core/src/services/organization.service.ts (5 hunks)
  • packages/tm-core/src/storage/api-storage.ts (1 hunks)
  • packages/tm-core/src/storage/file-storage/file-storage.ts (1 hunks)
  • packages/tm-core/src/storage/storage-factory.ts (2 hunks)
  • scripts/dev.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)

**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.

Files:

  • scripts/dev.js
🧠 Learnings (2)
📚 Learning: 2025-10-15T14:43:40.383Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1314
File: packages/tm-core/src/auth/credential-store.ts:92-94
Timestamp: 2025-10-15T14:43:40.383Z
Learning: In the claude-task-master codebase, `getCredentials()` in `credential-store.ts` defaults to `allowExpired: true` to enable Supabase refresh flows. The Supabase client automatically handles token refresh when credentials are expired but have a valid refresh token. The `SupabaseSessionStorage` updates the credentials after Supabase performs the refresh. This is an intentional design pattern where the credential store is passive storage and Supabase manages the active token lifecycle.

Applied to files:

  • packages/tm-core/src/auth/credential-store.ts
📚 Learning: 2025-09-02T21:51:41.383Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:0-0
Timestamp: 2025-09-02T21:51:41.383Z
Learning: In packages/tm-core/src/auth/config.ts, the BASE_DOMAIN configuration intentionally does not include runtime environment variable fallbacks like TM_BASE_DOMAIN or HAMSTER_BASE_URL. The maintainers prefer to keep these capabilities "hush hush" and undocumented, using only the build-time TM_PUBLIC_BASE_DOMAIN and the default value.

Applied to files:

  • packages/tm-core/src/auth/config.ts
  • packages/tm-core/src/storage/storage-factory.ts
🧬 Code graph analysis (3)
apps/cli/src/commands/auth.command.ts (1)
apps/cli/src/commands/context.command.ts (1)
  • ContextCommand (32-785)
packages/tm-core/src/auth/config.ts (1)
packages/tm-core/src/auth/types.ts (1)
  • AuthConfig (39-43)
packages/tm-core/src/clients/supabase-client.ts (1)
packages/tm-core/src/auth/types.ts (1)
  • AuthenticationError (88-100)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (19)
packages/tm-core/src/storage/api-storage.ts (1)

115-120: LGTM!

The getType() method provides a clean way to identify storage type at runtime, complementing FileStorage.getType() for consistent type identification across storage implementations.

packages/tm-core/src/storage/file-storage/file-storage.ts (1)

47-52: LGTM!

The getType() method provides consistent storage type identification, mirroring the implementation in ApiStorage.

packages/tm-core/src/storage/storage-factory.ts (2)

85-86: Runtime variable precedence established.

The change prioritizes TM_BASE_DOMAIN (runtime) over TM_PUBLIC_BASE_DOMAIN (build-time), establishing a clear precedence hierarchy that aligns with the PR's objective to support runtime environment variables for remote access.

Note: This represents a shift from the previous approach documented in learnings, where runtime variables like TM_BASE_DOMAIN were intentionally kept undocumented. This PR appears to formalize runtime variable support across the codebase.

Based on learnings


115-117: Complete fallback chain maintains backward compatibility.

The three-tier fallback (TM_BASE_DOMAINTM_PUBLIC_BASE_DOMAIN → hard-coded default) ensures backward compatibility while enabling runtime configuration.

packages/tm-core/src/clients/supabase-client.ts (1)

32-42: Consistent runtime-first precedence with clear error messaging.

The Supabase client configuration now follows the same runtime-first pattern as other configuration modules, with TM_SUPABASE_URL and TM_SUPABASE_ANON_KEY taking precedence over their build-time counterparts. The error message helpfully references both sets of environment variables.

scripts/dev.js (1)

12-22: Proper initialization order with dynamic import.

The reordering ensures environment variables load before any module-level code executes by:

  1. Moving dotenv.config() before other imports (line 14)
  2. Using dynamic import() with await (line 22) to defer module loading

This follows the coding guidelines for JavaScript files to avoid initialization order issues and ensures environment variables are available when modules initialize.

As per coding guidelines

packages/tm-core/src/auth/credential-store.ts (1)

27-28: Effective warning suppression prevents log spam.

The instance-level flag hasWarnedAboutMissingExpiration suppresses repeated warnings within a single run while still allowing the warning to reappear after new credentials are saved. This is particularly useful during auth flows where getCredentials() may be called multiple times with allowExpired: true to enable Supabase refresh flows.

Based on learnings

Also applies to: 89-93, 184-185

packages/tm-core/src/services/organization.service.ts (3)

30-35: Brief interface enriched with document details.

The optional document field extends the Brief interface with related document information, maintaining backward compatibility while enabling richer brief data.


180-185: Database join enriches brief list with document data.

The getBriefs query now joins document fields and materializes id, document_name, and title. The mapping correctly handles cases where no related document exists.

Also applies to: 210-217


245-251: Single brief retrieval includes document description.

The getBrief query extends the document join to include description, providing more comprehensive document data for individual brief lookups compared to the list view.

Also applies to: 280-288

packages/tm-core/src/services/export.service.ts (1)

361-366: Export API endpoint resolution aligns with broader configuration changes.

The API endpoint resolution now prioritizes TM_BASE_DOMAIN over TM_PUBLIC_BASE_DOMAIN, consistent with the runtime-first precedence established across other configuration modules in this PR. The conditional logic and URL construction cleanly utilize the resolved endpoint.

packages/tm-core/src/auth/config.ts (2)

10-16: Verify alignment with project policy on runtime environment variables.

Based on learnings, the maintainers previously preferred to keep runtime environment variable capabilities (TM_BASE_DOMAIN, HAMSTER_BASE_URL) "hush hush" and undocumented, relying only on build-time TM_PUBLIC_BASE_DOMAIN. This PR explicitly documents and prioritizes runtime variables, which may conflict with that policy.

Based on learnings.


24-24: Non-null assertion risks runtime error when both environment variables are undefined.

The non-null assertion BASE_DOMAIN! will cause TypeScript to assume BASE_DOMAIN is never undefined, but if both TM_BASE_DOMAIN and TM_PUBLIC_BASE_DOMAIN are undefined at runtime, this will result in baseUrl: undefined, which violates the AuthConfig interface requirement that baseUrl: string.

Apply this diff to provide a safe fallback:

-	baseUrl: BASE_DOMAIN!,
+	baseUrl: BASE_DOMAIN || 'https://tryhamster.com',

Or update the type to allow undefined and handle it at call sites:

 export interface AuthConfig {
-	baseUrl: string;
+	baseUrl: string | undefined;
 	configDir: string;
 	configFile: string;
 }
⛔ Skipped due to learnings
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/src/auth/config.ts:0-0
Timestamp: 2025-09-02T21:51:41.383Z
Learning: In packages/tm-core/src/auth/config.ts, the BASE_DOMAIN configuration intentionally does not include runtime environment variable fallbacks like TM_BASE_DOMAIN or HAMSTER_BASE_URL. The maintainers prefer to keep these capabilities "hush hush" and undocumented, using only the build-time TM_PUBLIC_BASE_DOMAIN and the default value.
apps/cli/package.json (1)

25-25: LGTM!

The addition of @inquirer/search aligns with the search-based brief selection feature introduced in apps/cli/src/commands/context.command.ts. The version constraint ^3.2.0 follows standard semver practices.

apps/cli/src/commands/context.command.ts (5)

160-169: LGTM!

The display logic correctly handles all combinations of briefName and briefId, showing a user-friendly format with the short ID in parentheses when both are available.


333-372: LGTM! Search implementation is well-structured.

The search-based brief selection handles filtering by title, full ID, and short ID. The optional chaining brief.document?.title safely handles missing document data, falling back to a formatted ID.

Minor observation: The fallback Brief ${brief.id.slice(0, 8)} is consistently applied throughout the file (lines 362, 378, 527), ensuring uniform display of briefs without document metadata.


376-390: LGTM!

The consistent derivation of briefName from brief.document?.title with a fallback to formatted ID ensures proper display across all flows. The success message on line 390 correctly reflects the selected brief's title.


526-527: Consistent brief name derivation.

The derivation pattern brief.document?.title || 'Brief ${brief.id.slice(0, 8)}' is consistently applied across all context-setting flows, ensuring uniform behavior.


723-768: LGTM! Well-structured post-auth context setup flow.

The setupContextInteractive method provides a clear, optional workflow for context setup after authentication. Key strengths:

  • User can opt out via confirmation prompt
  • Returns detailed status flags for caller
  • Graceful error handling with user-friendly fallback message
  • Appropriate integration with existing selectOrganization() and selectBrief() methods

The error handling on line 760-767 ensures that context setup failures don't break the authentication flow, which is the correct behavior since this is a post-auth enhancement.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 191a2fd and 2ef678f.

📒 Files selected for processing (1)
  • apps/cli/src/commands/auth.command.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/cli/src/commands/auth.command.ts (1)
apps/cli/src/commands/context.command.ts (1)
  • ContextCommand (32-785)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (1)
apps/cli/src/commands/auth.command.ts (1)

17-17: LGTM!

The import statement is correctly formatted and consistent with the existing ES module patterns.

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/add.prod.hamster branch from 2ef678f to 2100fe4 Compare October 16, 2025 15:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ef678f and 2100fe4.

📒 Files selected for processing (1)
  • apps/cli/src/commands/auth.command.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/cli/src/commands/auth.command.ts (1)
apps/cli/src/commands/context.command.ts (1)
  • ContextCommand (32-785)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (1)
apps/cli/src/commands/auth.command.ts (1)

17-17: LGTM!

The import is correctly placed and necessary for the post-auth context setup workflow.

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/add.prod.hamster branch from 2100fe4 to 6596fed Compare October 16, 2025 16:49
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.

1 participant