Skip to content

feat(observability): authenticate hosted Factory reporter - #289

Open
khaliqgant wants to merge 1 commit into
mainfrom
codex/factory-hosted-reporter-auth-0818
Open

feat(observability): authenticate hosted Factory reporter#289
khaliqgant wants to merge 1 commit into
mainfrom
codex/factory-hosted-reporter-auth-0818

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Aug 18, 2026

Copy link
Copy Markdown
Member

Summary

  • reuse Factory's existing private FACTORY_CLOUD_ACCESS_TOKEN_URL rotating-token provider for hosted telemetry delivery
  • bypass laptop Cloud login in hosted mode while preserving the existing local-session reporter path
  • keep telemetry fail-open: delivery failures stay in the durable outbox and do not change the Factory command result

Hosted contract

The reporter and Relayfile mount now share the existing hosted Cloud API resolver and the same validated access-token provider. The provider retains its URL/protocol, timeout, HTTP response, response-body, and relay_pa_ token-class checks.

This introduces no new secret, variable, or deployment gate. CLOUD_API_URL remains optional with its existing default, and FACTORY_CLOUD_ACCESS_TOKEN_URL remains the private rotating-token endpoint already supplied by the hosted runtime.

Cloud must land and deploy AgentWorkforce/cloud#3083 before this path is rolled out. That PR adds the narrow ingest authorization and verified Relay-workspace binding.

Verification

  • npx vitest run src/cli/fleet.test.ts src/mount/relayfile-cloud-mount-client.test.ts — 204 passed
  • npx vitest run --maxWorkers=4 — 1,757 passed, 1 skipped
  • npm run build
  • npx prettier --check src/cli/fleet.ts src/cli/fleet.test.ts src/mount/relayfile-cloud-mount-client.ts
  • git diff --check
  • changed-file high-entropy credential scan

The hosted success test exercises real reporter serialization, bearer auth, cloud instance identity, lifecycle batches, and a drained outbox without invoking local login. The 503 test proves the Factory command still succeeds while telemetry remains pending for retry.

Veto MCP tools requested by repository instructions were not present in this session, so no Veto result is claimed. Manual diff and secret reviews were completed.

Rollout and evidence

  1. Merge and deploy Cloud authorization first.
  2. Merge and release this Factory change.
  3. Let the factory-cloud cutover owner bump/deploy the Factory version.
  4. Run a real canary and observe it in the Cloud ledger, PostHog, and NightCTO.

No deployment or merge was performed here. Far-end delivery remains UNVERIFIED until step 4 is observed.


Summary by cubic

Authenticate the hosted Factory telemetry reporter using the existing private rotating-token endpoint. Previously the reporter required a local Cloud session; now, when hosted, it fetches a short‑lived relay_pa_ token and sends batches directly, preserving fail‑open behavior.

  • Hosted path is selected when FACTORY_CLOUD_ACCESS_TOKEN_URL is present; it resolves CLOUD_API_URL via resolveHostedCloudApiUrl, skips cloudSessionProvider, and validates URL/protocol and token class.
  • Fallback remains the local session path: if the hosted token is not configured, we use ensureCloudSession and the session’s apiUrl and access token.
  • Reporter still checks that the active account workspace matches the Factory config; otherwise, reporting is skipped.
  • Telemetry remains fail-open: 5xx leaves events in the durable outbox without affecting command exit codes.
  • API surface changes: export createHostedCloudAccessTokenProvider (with a default timeout), add test-only DI hooks cloudAccessTokenFetch and cloudReporterFetch; no new secrets or envs required, and CLOUD_API_URL remains optional.
  • Rollout: deploy AgentWorkforce/cloud#3083 first to enable ingest authorization and workspace binding. Hosted runtimes must provide FACTORY_CLOUD_ACCESS_TOKEN_URL; non-hosted users are unaffected.

Written for commit e2dd519. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 37a76451-59d1-48c6-90a3-41df11db9496

📥 Commits

Reviewing files that changed from the base of the PR and between 00fe7fa and e2dd519.

📒 Files selected for processing (3)
  • src/cli/fleet.test.ts
  • src/cli/fleet.ts
  • src/mount/relayfile-cloud-mount-client.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Hosted Cloud reporting now supports rotating access tokens and injected transports. API URL resolution and token timeout handling are centralized. Tests cover successful delivery, outbox draining, and fail-open behavior on telemetry HTTP 503 responses.

Changes

Hosted Cloud reporting

Layer / File(s) Summary
Hosted API and token provider
src/mount/relayfile-cloud-mount-client.ts
Exports hosted API URL resolution and access-token provider helpers. The provider uses a default timeout when none is supplied and reports normalized timeout values.
Hosted reporter construction
src/cli/fleet.ts
Adds injectable token and telemetry fetch implementations. Reporter setup selects hosted authentication when configured and retains the CloudSession fallback otherwise.
Hosted reporting integration coverage
src/cli/fleet.test.ts
Tests rotating-token retrieval, authenticated lifecycle delivery, outbox draining, and event preservation after telemetry HTTP 503 responses.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to e2dd5

The change authenticates hosted telemetry while preserving local reporting and fail-open command behavior; no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant FleetCli as Fleet CLI
  participant TokenEndpoint as Hosted access-token endpoint
  participant Telemetry as Cloud telemetry
  participant Outbox as File cloud event outbox
  FleetCli->>TokenEndpoint: Request rotating access token
  TokenEndpoint-->>FleetCli: Return access token
  FleetCli->>Telemetry: Submit lifecycle events with bearer token
  Telemetry-->>FleetCli: Return delivery result
  FleetCli->>Outbox: Drain delivered events
  Telemetry-->>FleetCli: Return HTTP 503
  FleetCli->>Outbox: Preserve pending events
Loading

Suggested reviewers: kjgbot, miyaontherelay

Poem

A rabbit packed tokens in a cloud-bound cart,
Sent lifecycle notes with a careful start.
When telemetry failed with a thundering roar,
The outbox kept every event in store.
“Try again,” whispered Hare, “the trail is secure.”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes authentication for the hosted Factory reporter, which is the primary change.
Description check ✅ Passed The description directly explains hosted authentication, local-session fallback, fail-open telemetry, rollout requirements, and verification.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/factory-hosted-reporter-auth-0818

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2dd51921f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/fleet.ts
Comment on lines +1625 to +1628
getAccessToken = createHostedCloudAccessTokenProvider({
url: runtimeEnv[FACTORY_CLOUD_ACCESS_TOKEN_URL_ENV]?.trim() ?? '',
fetchImpl: input.deps.cloudAccessTokenFetch ?? fetch,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound hosted-token fetches to reporter shutdown

When the private token endpoint hangs while an automatic flush is already running, close({ deadlineMs: 2_000 }) only stops awaiting the reporter operation; it does not cancel this hosted-token provider. The provider retains a referenced 10-second abort timer, and the in-flight reporter can perform three attempts, so main() may set the exit code while Node remains alive for roughly 30 seconds. Thread reporter cancellation into the token request, or otherwise ensure the request cannot keep the process alive after the shutdown deadline.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai Bot 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.

2 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/cli/fleet.ts">

<violation number="1" location="src/cli/fleet.ts:1625">
P2: Propagate reporter cancellation into `createHostedCloudAccessTokenProvider`; otherwise a hung hosted-token fetch continues past `close({ deadlineMs: 2_000 })` and can keep the CLI process alive until its timeout and retries finish.</violation>

<violation number="2" location="src/cli/fleet.ts:1626">
P2: Hosted mode is selected by the presence of FACTORY_CLOUD_ACCESS_TOKEN_URL, not by a non-empty value. If the variable is set to an empty or whitespace-only string, the code enters the hosted branch and createHostedCloudAccessTokenProvider throws synchronously on `new URL('')`, so hosted telemetry is bypassed/disabled (or the command errors) instead of falling back to the local-session path. Gate the hosted branch on a trimmed non-empty value and pass that value to the provider.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/cli/fleet.ts
let cloudFetch: typeof fetch | undefined
if (hasHostedAccessTokenConfig) {
apiUrl = resolveHostedCloudApiUrl(runtimeEnv)
getAccessToken = createHostedCloudAccessTokenProvider({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Propagate reporter cancellation into createHostedCloudAccessTokenProvider; otherwise a hung hosted-token fetch continues past close({ deadlineMs: 2_000 }) and can keep the CLI process alive until its timeout and retries finish.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/fleet.ts, line 1625:

<comment>Propagate reporter cancellation into `createHostedCloudAccessTokenProvider`; otherwise a hung hosted-token fetch continues past `close({ deadlineMs: 2_000 })` and can keep the CLI process alive until its timeout and retries finish.</comment>

<file context>
@@ -1594,15 +1613,28 @@ async function buildFactoryCloudReporter(input: {
+    let cloudFetch: typeof fetch | undefined
+    if (hasHostedAccessTokenConfig) {
+      apiUrl = resolveHostedCloudApiUrl(runtimeEnv)
+      getAccessToken = createHostedCloudAccessTokenProvider({
+        url: runtimeEnv[FACTORY_CLOUD_ACCESS_TOKEN_URL_ENV]?.trim() ?? '',
+        fetchImpl: input.deps.cloudAccessTokenFetch ?? fetch,
</file context>

Comment thread src/cli/fleet.ts
if (hasHostedAccessTokenConfig) {
apiUrl = resolveHostedCloudApiUrl(runtimeEnv)
getAccessToken = createHostedCloudAccessTokenProvider({
url: runtimeEnv[FACTORY_CLOUD_ACCESS_TOKEN_URL_ENV]?.trim() ?? '',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Hosted mode is selected by the presence of FACTORY_CLOUD_ACCESS_TOKEN_URL, not by a non-empty value. If the variable is set to an empty or whitespace-only string, the code enters the hosted branch and createHostedCloudAccessTokenProvider throws synchronously on new URL(''), so hosted telemetry is bypassed/disabled (or the command errors) instead of falling back to the local-session path. Gate the hosted branch on a trimmed non-empty value and pass that value to the provider.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/cli/fleet.ts, line 1626:

<comment>Hosted mode is selected by the presence of FACTORY_CLOUD_ACCESS_TOKEN_URL, not by a non-empty value. If the variable is set to an empty or whitespace-only string, the code enters the hosted branch and createHostedCloudAccessTokenProvider throws synchronously on `new URL('')`, so hosted telemetry is bypassed/disabled (or the command errors) instead of falling back to the local-session path. Gate the hosted branch on a trimmed non-empty value and pass that value to the provider.</comment>

<file context>
@@ -1594,15 +1613,28 @@ async function buildFactoryCloudReporter(input: {
+    if (hasHostedAccessTokenConfig) {
+      apiUrl = resolveHostedCloudApiUrl(runtimeEnv)
+      getAccessToken = createHostedCloudAccessTokenProvider({
+        url: runtimeEnv[FACTORY_CLOUD_ACCESS_TOKEN_URL_ENV]?.trim() ?? '',
+        fetchImpl: input.deps.cloudAccessTokenFetch ?? fetch,
+      })
</file context>

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