Skip to content

Promote the Hub-Hosted Secret and Env Readers to Main - #3512

Merged
ptr727 merged 1 commit into
mainfrom
develop
Oct 27, 2026
Merged

ptr727 merged 1 commit into
mainfrom
develop

Conversation

@ptr727

@ptr727 ptr727 commented Oct 26, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes the pull request merged into develop since release 2.0.1196.

  • #3509: the hub now hosts lib/sh/secrets.sh, the hardened secret and env readers a fleet repository runs on its own hosts. A repository declaring the new host-secrets type carries it byte-for-byte at lib/fleet/sh through a spec/files.json tree. repo_gate.py gains a carried-trees check, which compares each carried tree with the hub tree beside the gate and reports a difference as a warning that never fails the gate. carry.py gains the shared target_patterns and compare_declaration, which fix its post-apply comparison for a tree that does not prune. GOVERNANCE.md "Hub-Hosted Tooling" states why a runtime library is carried rather than reached, and "Repo-Scoped Secrets" states the reader rule.

Closes #3505

Constituent coverage

Pull request Merged head Coverage
#3509 85b2c4ad attested local pass at the merged head, base develop, recording 0 findings, and a Copilot round on an earlier head whose five findings were fixed or declined with evidence and resolved

🤖 Generated with Claude Code

… a Tree (#3509)

Implements #3505, with the design points the maintainer settled on the
issue before the first edit.

## What Changed

- **`lib/sh/secrets.sh`** is the hub's runtime library:
`unresolved_link_reason`, `secret_state`, the shape, content, set, and
full verdicts, `require_secret`, and `read_env_value`. Each function
body is byte-identical to the source implementation, compared with
`declare -f`. Its comments now describe the mechanism rather than the
adopter. The installer path helpers, the push interlock, and
`write_state_file` stay in the source repository. The source has no
owner check, so the issue's owner-exemption parameter had nothing to
parameterize.
- **`host-secrets`** is a new project type. `spec/project-types.json`
gives it `detect` and one intent check, `spec/scope-model.md` lists its
token, `spec/type-model.md` gains "Runtime Libraries", and the
conformance matrix has its row.
- **`spec/files.json`** carries `lib/sh` to `lib/fleet/sh` as a
`verbatim-tree` for `appliesTo: ["host-secrets"]`, so `carry.py`, the
audit, and the canonical sweep pick it up with no code of their own.
- **`repo_gate.py` `carried-trees`** compares each carried tree a
scanned repository tracks with the hub tree beside the gate, the pinned
action's in CI. It loads the hub's own `scripts/carry.py` and reuses its
tree functions, including the new `target_patterns` and
`compare_declaration` that `carry.py`'s own check and post-apply
comparison now share. A difference is a `note:` plus a `::warning`
annotation and never a finding. A repository tracking `spec/files.json`
is a hub and compares nothing. A tree that cannot be compared, or a
`carry.py` that will not load or run, says so in a note.
- **`GOVERNANCE.md`**: "Hub-Hosted Tooling" states why code a
repository's own runtime executes is carried rather than reached.
"Repo-Scoped Secrets" states the reader rule the type's check judges,
and "Repository Layout" lists `lib/`.
- **Tests**: `tests/test_secrets_sh.py` drives every verdict and the env
read against constructed files. `tests/test_repo_gate.py` covers the new
check and `gate_hub_root`. `tests/test_cli_usage.py` lists the library
as sourced rather than run.

## Verification

- The full unit suite under `tests/requirements.txt` passes: 3023 tests,
7 skipped.
- Mutating the library, by dropping `-u BASH_ENV` or the `unset`,
reading `$2` at the end, dropping `/dev/null`, reordering the set
verdict, or sourcing in process, fails the case written for each fault.
- `spec/validate.py`, `build_dist.py --check`, the prose gate with
comments allowed, every `repo_gate.py` check, and the Docker lint
wrapper's seven linters are clean.
- `carried-trees` was run against two downstream checkouts. Blog's
`.github/skills` matches the hub. One checkout's copy differs in 37
files and warns as designed. The check also runs under Python 3.12, the
runner's system interpreter.

## Local Review

Each push's content went through recorded `local-strict-review` passes
at the `frontier` tier, and each push spent its two-round edit budget.
The seven pushes' passes raised 11, 15, and 4 findings, then 6 and 4,
then 4, 4, and 3, then 5 and 3, then 2 and 2, then 3 and 1, then 3 and
1, and the eighth push's pass raised none. The seventh push also fixes
the Windows unit test job, which failed on an unresolved 8.3 temp path
in the new `carry.run` case. Every `introduced` finding is answered.

### Declined in the sixth push

- The import-time `uv python find` probe in `tests/host_capability.py`
follows the file's existing eager `can_symlink()` probe.

### Pre-existing findings, not filed

- `pre-existing`: `tests/test_repo_gate.py`, whose write-verb scan reads
`scripts/repo_gate.py`, a `run_path` shim, rather than the gate under
`.github/actions/repo-gate/`.

### Declined, with evidence

- The library's own hardening (the positional-parameter guard, `grep -D
skip`, the `readarray -d /` split): the bodies move byte-identical by
the issue's design, so a change to them is its own issue in the
authoring repository.
- The note not naming the hub commit: the pinned action's tree is an
archive with no `.git`, and the run log already names the action's pin.
- Untracked files in a local hub checkout's source tree: `carry.py`'s
own `inventory` reads the source the same way, so the gate and a carry
agree.
- CRLF working-tree bytes on a Windows checkout: every registry entry
declares `lineEndings: lf`.
- The `spec/files.json` hub test catching an unpruned template copy: the
note says "is a hub", so the result is visible rather than silent.
- The issue's point that the same rule gives `hub_fetch_run.py` a
declared home: that loader is not a `spec/files.json` tree, and the
"Hub-Hosted Tooling" paragraph beginning "A loader is outside this
section" already governs it.
- The `try` around the manifest read: `load_json` belongs to a
`carry.py` of whatever hub version the pin holds, so the reason for the
other broad catches covers it too.
- Folding the gate test helpers `TestCarriedTrees.write` and
`TestGateHubRoot.place` into one: a preference between defensible forms,
which "Review the Change" says to omit.

### Dropped findings

- The module docstring's table framing, and long sentences in comments
and docstrings, which an advisory check reports and no gate enforces.
- `spec/audit.py` `check_tree_verbatim` keeps its own blob-based
statement of the tree ownership rule. That file is untouched here, and
it reads blobs rather than inventories.

The pull request carries the `comments` label. The added comments are
each function's caller contract and the measured reasons behind each
check.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings October 26, 2026 23:06
@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Three unresolved findings remain, including a critical symlink-handling issue in the secret reader.

2 open issues
What changed in this PR

This pull request promotes the hub-hosted secret and environment readers to main, adding the host-secrets project type, carried-tree contract, repository-gate support, tests, and governance documentation.

Changes:

  • Adds and tests lib/sh/secrets.sh for secret validation and isolated environment-file reads.
  • Defines host-secrets and carries lib/sh to lib/fleet/sh through spec/files.json.
  • Adds carried-tree comparison support, updated carry behavior, workflow documentation, and governance guidance.

Unresolved findings:

  • lib/sh/secrets.sh:242 — moderate, P1: Preserve the requested environment variable name while sourcing the file.
  • lib/sh/secrets.sh:61 — critical, P1: Reject resolving parent symlinks before reading secrets.
  • spec/files.json:6 — moderate, P1: Carry the reader tests with the runtime tree.
File Description
tests/​test_secrets_sh.py Tests secret verdicts, required secrets, and environment-file reads.
tests/​test_repo_gate.py Tests carried-tree comparison, warnings, and hub-root detection.
tests/​test_cli_usage.py Classifies the shell library as sourced rather than executed.
tests/​test_carry.py Tests non-pruned tree ownership and comparison helpers.
tests/​host_capability.py Adds Python 3.12 capability detection for gate tests.
spec/​type-model.md Documents runtime-library project types.
spec/​scope-model.md Adds host-secrets to the project-type selector namespace.
spec/​project-types.json Defines the host-secrets type and reader contract.
spec/​files.json Declares the lib/sh to lib/fleet/sh carried tree.
spec/​fidelity-model.md Clarifies byte-for-byte tree comparison.
scripts/​README.md Documents the carried-trees gate behavior.
scripts/​carry.py Shares target ownership and declaration comparison logic.
reports/​conformance-matrix.md Adds the host-secrets overlay to the conformance matrix.
lib/​sh/​secrets.sh Provides the hub-hosted secret and environment readers.
GOVERNANCE.md Defines runtime-library carrying and repo-scoped secret-reader rules.
AUDIT.md Adds host-secrets discovery guidance.
.github/​workflows/​validate-task.yml Documents carried-tree exclusion handling.
.github/​actions/​repo-gate/​repo_gate.py Implements the non-blocking carried-tree currency check.
.github/​actions/​repo-gate/​action.yml Updates the gate description for carried-tree checks.

Review effort: Lite

Comment thread lib/sh/secrets.sh
Comment thread lib/sh/secrets.sh
@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.54%. Comparing base (d65fb3b) to head (1ab4c89).
⚠️ Report is 428 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3512      +/-   ##
==========================================
+ Coverage   81.11%   81.54%   +0.42%     
==========================================
  Files          26       26              
  Lines        8914     8918       +4     
==========================================
+ Hits         7231     7272      +41     
+ Misses       1683     1646      -37     
Flag Coverage Δ
python-3.13 81.54% <100.00%> (+0.42%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ptr727

ptr727 commented Oct 26, 2026

Copy link
Copy Markdown
Owner Author

Answering the review body's third unresolved finding, spec/files.json:6, "Carry the reader tests with the runtime tree", which has no thread. Declined. The maintainer replaced that design point before the first edit, as recorded in #3505 (comment), answer 2: "Hub CI only. A consumer carries the library alone, and the stale-copy check proves its copy is byte-identical to a tested hub version, so validate-task.yml does not change." The same finding was declined on #3509 with the same evidence.

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.

Host the Hardened Secret and Env Readers in the Hub and Carry Them as a Synced Copy

2 participants