Skip to content

feat(launching): record and revalidate launch receipts - #341

Open
bobtista wants to merge 4 commits into
developmentfrom
feat/launch-receipt
Open

feat(launching): record and revalidate launch receipts#341
bobtista wants to merge 4 commits into
developmentfrom
feat/launch-receipt

Conversation

@bobtista

@bobtista bobtista commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Record what each successful launch consisted of and cheaply compare subsequent launches against that receipt so configuration and filesystem drift is visible.

Changes

  • Write a versioned JSON receipt into each workspace after a successful launch.
  • Record executable identity, manifest versions, retail archive roots, per-archive size and timestamp fingerprints, the GenHub-built child environment, and resolved variant identity.
  • Hash the executable when recording while using inexpensive existence, size, and timestamp checks during routine revalidation.
  • Compare the previous receipt with both current filesystem state and the upcoming launch configuration.
  • Return drift on the launch result and surface it as a capped informational notification without changing successful-launch presentation.
  • Keep receipt-writing failures non-fatal and avoid recording inherited environment variables that may contain secrets.

Testing

  • dotnet test GenHub/GenHub.sln -c Release — 1,476 tests passed.

Risks and rollback

Routine revalidation deliberately avoids content hashing, so a same-size replacement with a deliberately preserved timestamp is not detected. Receipt persistence is best-effort and does not fail an otherwise successful launch. Reverting this PR removes receipt recording and drift notifications.

Related issues

Fixes #323

Greptile Summary

The PR adds persistent, versioned launch receipts and reports configuration or filesystem drift on subsequent launches.

  • Captures executable, manifest, archive, environment, and resolved variant metadata after a successful launch.
  • Revalidates the previous receipt before workspace preparation and compares it with the upcoming launch configuration.
  • Surfaces capped informational drift notifications while keeping receipt failures non-fatal.
  • Registers the receipt service and adds launch, service, and view-model tests.

Confidence Score: 4/5

The PR is not yet safe to merge because launch receipts still expose profile-defined environment secrets through persisted JSON, logs, and UI notifications.

The entire child-process environment is copied into the receipt without filtering, and drift messages interpolate old and new values verbatim, leaving the previously reported credential-disclosure path reachable.

Files Needing Attention: GenHub/GenHub/Features/Launching/LaunchReceiptService.cs; GenHub/GenHub/Features/Launching/GameLauncher.cs

Important Files Changed

Filename Overview
GenHub/GenHub/Features/Launching/LaunchReceiptService.cs Implements receipt persistence and drift comparison across executable, archive, manifest, environment, and variant state.
GenHub/GenHub/Features/Launching/GameLauncher.cs Integrates receipt revalidation, configuration comparison, persistence, and warning propagation into the launch lifecycle.
GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs Displays capped informational notifications for receipt drift without altering successful-launch presentation.
GenHub/GenHub/Infrastructure/DependencyInjection/GameLaunchingModule.cs Registers the launch receipt service in the shared launching module.

Sequence Diagram

sequenceDiagram
    participant UI as Launcher ViewModel
    participant Launcher as GameLauncher
    participant Receipt as LaunchReceiptService
    participant Workspace as WorkspaceManager
    participant Process as Game Process Manager
    UI->>Launcher: Launch profile
    Launcher->>Receipt: Revalidate previous receipt
    Receipt-->>Launcher: Filesystem drift and previous receipt
    Launcher->>Workspace: Prepare workspace
    Workspace-->>Launcher: Workspace and executable
    Launcher->>Receipt: Compare upcoming configuration
    Receipt-->>Launcher: Configuration drift
    Launcher->>Process: Start process
    Process-->>Launcher: Process information
    Launcher->>Receipt: Record latest receipt
    Launcher-->>UI: Success with drift warnings
Loading

Reviews (3): Last reviewed commit: "feat(launching): surface receipt drift a..." | Re-trigger Greptile

Context used:

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • development

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4fb598d4-a3e8-4dec-a3f6-51e0759c1447

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

Comment on lines +65 to +68
foreach (var (variableName, value) in context.EnvironmentVariables)
{
receipt.EnvironmentVariables[variableName] = value;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Environment secrets leak into receipts

When a profile defines a secret-bearing child-process environment variable, RecordLaunchAsync persists its value in plaintext, and later drift comparisons include the old or new value in logs and UI notifications. This exposes credentials to anyone who can read the workspace, logs, or notification. How this was verified: The unrestricted profile environment dictionary was traced unchanged through the launch context into JSON serialization and value-interpolating drift messages.

Knowledge Base Used: Game Profiles and Launching

Prompt To Fix With AI
This is a comment left during a code review.
Path: GenHub/GenHub/Features/Launching/LaunchReceiptService.cs
Line: 65-68

Comment:
**Environment secrets leak into receipts**

When a profile defines a secret-bearing child-process environment variable, `RecordLaunchAsync` persists its value in plaintext, and later drift comparisons include the old or new value in logs and UI notifications. This exposes credentials to anyone who can read the workspace, logs, or notification. **How this was verified:** The unrestricted profile environment dictionary was traced unchanged through the launch context into JSON serialization and value-interpolating drift messages.

**Knowledge Base Used:** [Game Profiles and Launching](https://app.greptile.com/genhub/-/custom-context/knowledge-base/community-outpost/genhub/-/docs/game-profiles-launching.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +186 to +190
private static bool PathsEqual(string left, string right) =>
string.Equals(
Path.TrimEndingDirectorySeparator(left),
Path.TrimEndingDirectorySeparator(right),
StringComparison.Ordinal);

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 Path comparison ignores Windows semantics

PathsEqual uses ordinal comparison and only trims trailing separators, so equivalent Windows paths with different casing or slash representation are reported as executable or archive-root drift. Using platform-aware, canonical path comparison avoids misleading notifications for unchanged launches.

Knowledge Base Used: Game Profiles and Launching

Prompt To Fix With AI
This is a comment left during a code review.
Path: GenHub/GenHub/Features/Launching/LaunchReceiptService.cs
Line: 186-190

Comment:
**Path comparison ignores Windows semantics**

`PathsEqual` uses ordinal comparison and only trims trailing separators, so equivalent Windows paths with different casing or slash representation are reported as executable or archive-root drift. Using platform-aware, canonical path comparison avoids misleading notifications for unchanged launches.

**Knowledge Base Used:** [Game Profiles and Launching](https://app.greptile.com/genhub/-/custom-context/knowledge-base/community-outpost/genhub/-/docs/game-profiles-launching.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@kilo-code-bot

kilo-code-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 1 Issue Found (Already Reported) | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 0
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
GenHub/GenHub/Features/Launching/LaunchReceiptService.cs 68 Environment secrets leak into receipts and notifications (already reported by greptile-apps[bot])
Files Reviewed (15 files)
  • GenHub/GenHub.Core/Constants/FileTypes.cs
  • GenHub/GenHub.Core/Interfaces/Launching/ILaunchReceiptService.cs
  • GenHub/GenHub.Core/Models/GameProfile/GameLaunchInfo.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceipt.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptArchiveEntry.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptArchiveRoot.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptContext.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptDriftReport.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptExecutable.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptVariant.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/ViewModels/GameProfileLauncherViewModelTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/GameLauncherTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/LaunchReceiptServiceTests.cs
  • GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs
  • GenHub/GenHub/Features/Launching/GameLauncher.cs
  • GenHub/GenHub/Features/Launching/LaunchReceiptService.cs
  • GenHub/GenHub/Infrastructure/DependencyInjection/GameLaunchingModule.cs

Notes

  • The CRITICAL security issue regarding environment variable persistence in receipts and drift notifications has already been reported by greptile-apps[bot] on line 68 of LaunchReceiptService.cs
  • No new issues were found beyond those already reported
  • The code is otherwise well-structured with comprehensive test coverage
  • Fix link: Fix these issues in Kilo Cloud

@kilo-code-bot

kilo-code-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
GenHub/GenHub/Features/Launching/LaunchReceiptService.cs 68 Environment secrets leak into receipts, drift logs, and UI notifications (already reported by greptile-apps[bot])

WARNING

File Line Issue
GenHub/GenHub/Features/Launching/LaunchReceiptService.cs 128 Unguarded receipt-field access after the parse can abort a launch that must never block on receipts
GenHub/GenHub/Features/Launching/LaunchReceiptService.cs 190 PathsEqual ignores Windows path semantics, causing false drift reports (already reported by greptile-apps[bot])
Files Reviewed (17 files)
  • GenHub/GenHub.Core/Constants/FileTypes.cs
  • GenHub/GenHub.Core/Interfaces/Launching/ILaunchReceiptService.cs
  • GenHub/GenHub.Core/Models/GameProfile/GameLaunchInfo.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceipt.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptArchiveEntry.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptArchiveRoot.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptContext.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptDriftReport.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptExecutable.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptVariant.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/ViewModels/GameProfileLauncherViewModelTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/GameLauncherTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/LaunchReceiptServiceTests.cs
  • GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs
  • GenHub/GenHub/Features/Launching/GameLauncher.cs
  • GenHub/GenHub/Features/Launching/LaunchReceiptService.cs - 3 issues
  • GenHub/GenHub/Infrastructure/DependencyInjection/GameLaunchingModule.cs

Fix these issues in Kilo Cloud

Previous Review Summary (commit 070d578)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 070d578)

Status: 1 Issue Found (Already Reported) | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 0
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
GenHub/GenHub/Features/Launching/LaunchReceiptService.cs 68 Environment secrets leak into receipts and notifications (already reported by greptile-apps[bot])
Files Reviewed (16 files)
  • GenHub/GenHub.Core/Constants/FileTypes.cs
  • GenHub/GenHub.Core/Interfaces/Launching/ILaunchReceiptService.cs
  • GenHub/GenHub.Core/Models/GameProfile/GameLaunchInfo.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceipt.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptArchiveEntry.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptArchiveRoot.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptContext.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptDriftReport.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptExecutable.cs
  • GenHub/GenHub.Core/Models/Launching/LaunchReceiptVariant.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/ViewModels/GameProfileLauncherViewModelTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/GameLauncherTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/LaunchReceiptServiceTests.cs
  • GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs
  • GenHub/GenHub/Features/Launching/GameLauncher.cs
  • GenHub/GenHub/Features/Launching/LaunchReceiptService.cs
  • GenHub/GenHub/Infrastructure/DependencyInjection/GameLaunchingModule.cs

Notes

  • The CRITICAL security issue regarding environment variable persistence in receipts and drift notifications has already been reported by greptile-apps[bot] on line 68 of LaunchReceiptService.cs
  • No new issues were found beyond those already reported
  • The code is otherwise well-structured with comprehensive test coverage
  • Fix link: Fix these issues in Kilo Cloud

Reviewed by glm-5.2 · Input: 74.4K · Output: 21.9K · Cached: 817.3K

@bobtista
bobtista force-pushed the feat/launch-receipt branch from 070d578 to 970d237 Compare August 3, 2026 12:43
@bobtista
bobtista changed the base branch from feat/native-launch to development August 3, 2026 12:44
@bobtista

bobtista commented Aug 3, 2026

Copy link
Copy Markdown
Author

Rebased onto development and retargeted from feat/native-launch.

feat/native-launch was squash-merged as #332, so this PR was stacked on a branch that no longer exists in development's history. Retargeting alone would have produced a diff of 63 files, +2427/-3615 — one that deletes the work merged since #331 (#332, #337, #338, #339, #348, #349). That is the squash-orphaning failure #327 describes.

Instead the four commits unique to this branch were replayed onto development with git rebase --onto origin/development d1adeeb. No conflicts. The diff is now 17 files, +1961/-2 — this branch's own work and nothing else.

The rebase applied cleanly but the test suite has not been run against the rebased branch, so CI here is the first verification. #340 received the equivalent rebase and passed 1,553 tests.

No approvals existed, so nothing was dismissed by the force-push.

}

report.Receipt = receipt;
CompareExecutable(receipt.Executable, report);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Unguarded receipt-field access can abort a launch that the documented invariant says must never block on receipts.

The JSON parse immediately above is wrapped defensively, but CompareExecutable(receipt.Executable, report) and the foreach (... in receipt.ArchiveRoots) below it are not. A corrupt or tampered receipt that still parses successfully — e.g. "Executable": null, "ArchiveRoots": null, or a null archive-root entry — produces an unhandled NullReferenceException here; an uncaught SecurityException or transient IO error from FileInfo inside CompareExecutable has the same effect. RevalidateAsync is awaited on the launch path (RevalidateLaunchReceiptAsync -> LaunchProfileAsync), so the exception propagates and fails the launch, contradicting the stated guarantee that receipt and drift issues never block a launch. Wrap this block in the same try/catch used for the parse, or null-guard the receipt fields before use.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

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