Skip to content

feat(analytics): persist installer setup identity - #18

Open
patrickleet wants to merge 6 commits into
mainfrom
feat/webanalytics-session-identity
Open

patrickleet wants to merge 6 commits into
mainfrom
feat/webanalytics-session-identity

Conversation

@patrickleet

@patrickleet patrickleet commented Aug 12, 2026 •

Copy link
Copy Markdown

Summary

  • persist the gateway-injected setup UUID only after a verified CLI install
  • preserve the first pending install identity across upgrades
  • add owner-only storage and create-without-replacement semantics
  • add Bats coverage and CI wiring

Security

  • rejects malformed UUIDs, symlink/non-regular targets, foreign ownership, insecure existing files, and unsafe config directories
  • never prints the setup ID and fails open for installation availability

Verification

  • bash -n install.sh
  • actionlint .github/workflows/test-install.yml
  • manual macOS permission/retry checks
  • Bats suite runs in CI

Summary by CodeRabbit

  • New Features

    • Securely saves a validated setup identifier for future installer use.
    • Protects existing configuration by checking file ownership, permissions, type, symlinks, and concurrent access.
    • Supports library-only installer execution for safer integrations.
  • Bug Fixes

    • Prevents unsafe or malformed configuration data from being modified or exposed.
  • Tests

    • Added comprehensive coverage for setup-identifier persistence, security checks, permissions, and environment handling.
    • Expanded installation checks across supported platforms.

@coderabbitai

coderabbitai Bot commented Aug 12, 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: ASSERTIVE

Plan: Pro Plus

Run ID: 243a8971-31c7-4cf7-aca8-159e032057aa

📥 Commits

Reviewing files that changed from the base of the PR and between d00fd70 and 92dcef9.

📒 Files selected for processing (3)
  • .github/workflows/test-install.yml
  • install.sh
  • tests/install-setup-id.bats

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


Walkthrough

The installer now persists validated UUIDv4 setup IDs in protected configuration state. It rejects unsafe paths and preserves valid existing state. New Bats coverage and a required CI job validate the behavior.

Changes

Setup identity persistence

Layer / File(s) Summary
Persist setup identity and validate safety
install.sh, tests/install-setup-id.bats
The installer validates UUIDv4 values, securely writes setup state, preserves valid existing IDs, rejects unsafe targets, restores umask, and supports library-only execution. Bats tests cover these cases.
Run setup-state checks in CI
.github/workflows/test-install.yml
The workflow adds restricted setup-state testing, pins checkout actions, disables credential persistence, and requires Linux, macOS, and setup-state checks to pass.

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

Merge Risk: 🔵 Low · up to 92dce

The installer now persists a setup identity, but an insecure existing configuration directory could let another account replace the identity file and access that value. The change is otherwise mergeable with explicit owner awareness or follow-up to validate directory ownership and permissions.

Sequence Diagram(s)

sequenceDiagram
  participant Installer as install.sh
  participant Binary as Installed binary
  participant State as GitKB setup state
  participant CI as GitHub Actions
  Installer->>Binary: Verify installation
  Installer->>State: Persist validated setup UUID
  State-->>Installer: Accept or reject state update
  CI->>Installer: Check shell syntax
  CI->>State: Run setup-state security tests
Loading

Poem

A rabbit checks the UUID at night

It locks the state file snug and tight
Unsafe links hop away
Tests guard the gate each day
CI makes the green light bright

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: persisting the installer setup identity.
Full details: Docstring Coverage

Explanation

Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/webanalytics-session-identity

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/test-install.yml (1)

166-184: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not mask a failed setup-state job when platform jobs are skipped.

test-setup-state has no upstream-success condition. If the upstream workflow fails, test-linux and test-macos are skipped, then Lines 175-178 make results succeed before Line 183 checks a failed test-setup-state result.

Apply the same workflow_run condition to test-setup-state, and only take the skipped-success path when all three test jobs are skipped.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/test-install.yml around lines 166 - 184, Update the
test-setup-state job condition to use the same workflow_run success requirement
as test-linux and test-macos. In the Aggregate results step, change the early
skipped-success path so it applies only when test-setup-state, test-linux, and
test-macos all have a skipped result, ensuring a failed setup job cannot be
masked.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/test-install.yml:
- Around line 25-35: Update the test-setup-state job to pin actions/checkout@v4
to a full commit SHA, add persist-credentials: false to that checkout step, and
define job-level permissions with contents: read. Apply the same checkout
hardening to every other job in this workflow that checks out repository code.

In `@install.sh`:
- Around line 62-105: Update the install attribution persistence function
containing umask 077 so its temporary restrictive umask cannot leak into the
caller when install.sh is sourced. Run the function body in a subshell or save
the previous umask and restore it on every return path, including mkdir,
validation, existing-state, and temporary-file failure exits.
- Around line 49-57: Validate config_home for symlinks or non-directory existing
paths before deriving or creating state_dir, so mkdir -p cannot follow an
attacker-selected XDG_CONFIG_HOME target. Preserve the existing state_dir
validation and add a Bats test covering a symlinked XDG_CONFIG_HOME.

In `@scripts/atc-setup-identity-proof.sh`:
- Around line 31-35: Update the checksum selection in the proof setup flow to
verify shasum is available before invoking it. When neither sha256sum nor shasum
exists, set status=failed and prevent the proof from emitting a passed result
with an empty evidence_sha; preserve the existing checksum behavior when either
utility is present.

In `@tests/install-setup-id.bats`:
- Around line 21-22: Add a reusable permission-check helper in the Bats test
file, following the installer proof script’s fallback from GNU stat -c '%a' to
macOS stat -f '%Lp'. Update all affected setup-id and gitkb permission
assertions to use this helper while preserving the expected 600 and 700 values.

---

Outside diff comments:
In @.github/workflows/test-install.yml:
- Around line 166-184: Update the test-setup-state job condition to use the same
workflow_run success requirement as test-linux and test-macos. In the Aggregate
results step, change the early skipped-success path so it applies only when
test-setup-state, test-linux, and test-macos all have a skipped result, ensuring
a failed setup job cannot be masked.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a1d0c5eb-34ef-4782-a611-585e8ac1fc4d

📥 Commits

Reviewing files that changed from the base of the PR and between 8e5f7f3 and bad9508.

📒 Files selected for processing (5)
  • .atc/productionize-proof.json
  • .github/workflows/test-install.yml
  • install.sh
  • scripts/atc-setup-identity-proof.sh
  • tests/install-setup-id.bats

Comment thread .github/workflows/test-install.yml
Comment thread install.sh
Comment thread install.sh Outdated
Comment thread scripts/atc-setup-identity-proof.sh Outdated
Comment thread tests/install-setup-id.bats Outdated
Emit recursively key-sorted JSON with exactly one trailing newline so current ATC can verify the pinned disposable acceptance receipt.

[[tasks/posthog-baseline-v1-reconciliation-epic/correlation-smoke]]
Implements [[tasks/posthog-baseline-v1-reconciliation-epic/install-download-join]]
@patrickleet

Copy link
Copy Markdown
Author

Productionization review started for pinned head d00fd70057cc907e695b9af4c49389d9edcf99f8. I will review the full PR, apply and validate any bounded fixes, run the configured proof gate, and leave the PR open.

Implements [[webanalytics-session-identity]]

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@install.sh`:
- Around line 43-45: Update the UUID validation in persist_setup_id and the
existing setup-id file validation to reject multi-line or appended content,
requiring exactly one valid UUID followed by the expected trailing newline.
Replace line-oriented grep checks with whole-string validation, and add Bats
coverage for valid UUID values plus setup IDs and state files containing
appended lines.
- Around line 55-58: Update the config_home validation block in install.sh to
reject existing directories not owned by the current user or writable by
group/other users, while preserving the existing symlink and non-directory
checks. Add a Bats test covering a foreign-owned or group/other-writable
configuration home and verify attribution state is not written.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 28be1633-3fe0-453d-9650-edcd44a0e291

📥 Commits

Reviewing files that changed from the base of the PR and between bad9508 and d00fd70.

📒 Files selected for processing (5)
  • .github/workflows/test-install.yml
  • .gitignore
  • install.sh
  • scripts/atc-setup-identity-proof.sh
  • tests/install-setup-id.bats

Comment thread install.sh Outdated
Comment thread install.sh
Comment on lines +55 to +58
if [ -L "$config_home" ] || { [ -e "$config_home" ] && [ ! -d "$config_home" ]; }; then
warn "Could not save install attribution state: unsafe GitKB config directory"
return 0
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate existing config_home ownership and permissions.

An existing config_home can be foreign-owned or writable by another account. That account can replace gitkb after the state-directory checks. The installer can then create the temporary file in an attacker-controlled directory and disclose the setup ID before the hard-link operation fails.

Reject an existing config_home unless the current user owns it and group and other users cannot write it. Add a Bats case for an insecure configuration home.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@install.sh` around lines 55 - 58, Update the config_home validation block in
install.sh to reject existing directories not owned by the current user or
writable by group/other users, while preserving the existing symlink and
non-directory checks. Add a Bats test covering a foreign-owned or
group/other-writable configuration home and verify attribution state is not
written.

@patrickleet

Copy link
Copy Markdown
Author

Review pass 1 found one actionable workflow issue on d00fd70057cc907e695b9af4c49389d9edcf99f8: the setup-state job lacks the platform jobs’ workflow_run success guard, while the aggregate job treats only the two platform skips as success. A failed upstream run can therefore execute the wrong setup test path and mask its failure. A bounded fix is required.

Ref: [[tasks/posthog-baseline-v1-reconciliation-epic/install-download-join]]

Implements [[feat/webanalytics-session-identity]]
@patrickleet

Copy link
Copy Markdown
Author

Fix pass 1 is confirmed at e27861ce131cce2ddd8254d0f5b30630de406f84. The setup-state job now shares the workflow_run success guard, and the aggregate skipped-success path requires all three test jobs to be skipped. Validation: actionlint passed, bash -n install.sh passed, the disposable installer identity proof passed, and the worktree is clean.

Implements [[feat/webanalytics-session-identity]]

@patrickleet

Copy link
Copy Markdown
Author

Review pass 2 found one actionable installer validation issue on e27861ce131cce2ddd8254d0f5b30630de406f84: the line-oriented UUID check accepts a multiline environment value when any line is valid, then persists the full malformed value. The same check can accept non-canonical existing state. Exact scalar and exact-file validation plus regression coverage are required.

Ref: [[tasks/posthog-baseline-v1-reconciliation-epic/install-download-join]]

Implements [[feat/webanalytics-session-identity]]
@patrickleet

Copy link
Copy Markdown
Author

Fix pass 2 is confirmed at 2a5583f8edecae4b6eaa446e258a4382bef5f2ce. Setup IDs are now validated as exact Bash scalars, existing state must byte-match one canonical UUID line, and focused tests/proof assertions cover multiline input and non-canonical state. Validation: shell syntax, actionlint, the updated disposable proof, and diff checks passed; the worktree is clean.

Implements [[feat/webanalytics-session-identity]]

@patrickleet

Copy link
Copy Markdown
Author

Review pass 3 is clean on final head 2a5583f8edecae4b6eaa446e258a4382bef5f2ce. The complete PR diff was re-reviewed after both fixes. No unresolved findings remain; shell syntax, actionlint, focused setup-identity acceptance checks, the disposable proof script, and clean-worktree/head checks passed.

Ref: [[tasks/posthog-baseline-v1-reconciliation-epic/install-download-join]]

@patrickleet

Copy link
Copy Markdown
Author

Productionization completed successfully on final head 2a5583f8edecae4b6eaa446e258a4382bef5f2ce. Three complete review passes resolved two findings in two fenced fix passes. The pinned disposable proof passed, and the setup-state, Linux, macOS, and aggregate GitHub Actions checks are green. No findings or blockers remain; this pull request remains open for human disposition.

Implements [[feat/webanalytics-session-identity]]

@mateodelnorte

Copy link
Copy Markdown
Contributor

Should this id be created by git-kb's binary, instead? That way, regardless of how it's installed (curl or brew), there's a single method?

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