Skip to content

feat: moat partner hardening — granted-repo scanning, secrets zero-policy, evict-then-guard tasks - #1425

Merged
4444J99 merged 2 commits into
mainfrom
feat/moat-partner-hardening
Jul 23, 2026
Merged

feat: moat partner hardening — granted-repo scanning, secrets zero-policy, evict-then-guard tasks#1425
4444J99 merged 2 commits into
mainfrom
feat/moat-partner-hardening

Conversation

@4444J99

@4444J99 4444J99 commented Jul 23, 2026

Copy link
Copy Markdown
Member

PR 3 of the partner-partition plan (reads #1407's ACCESS registry; independent of #1423).

  • moat-audit.py: unions partner-granted repos into the audited list and scans them regardless of visibility; names-only Actions-secrets zero-policy on granted repos (live counts today: 0/0/0, so the RED guards the future); guard_owed cite when a granted repo has no moat-guard entry; --require-guard flag = the executable done-predicate for evict-then-guard work.
  • estate.yaml: repo_overrides class content-engine--asset-amplifier + sovereign-systems--elevate-align as operation_private (they fell to protection-exempt private_unreviewed).
  • seed-tasks.py: CONST-STYX-MOAT + CONST-CANNIBAL-MOAT rows — evict the tuned values FIRST, then guard (a guard entry for an in-tree value reddens instantly, which is why no guard entries land in this PR).
  • Pre-existing trunk finding surfaced while verifying: public-record-data-scrapper leaks 4 declared values (red on main before this diff) — homed as board task HEAL-SCRAPPER-MOAT-EVICT (system_debt, broker-acknowledged).

Verification: py_compile green; seeder dry-run validates both MOAT rows through the intake contract; gitvs doctor --parity-only drift == ∅; live audit exercises every new path (granted=partner marks, guard-owed cites, secrets 0); verify-scoped.shScoped verification passed.

🤖 Generated with Claude Code

…licy, evict-then-guard tasks

moat-audit.py now reads the ACCESS registry (one knob: LIMEN_GITVS_ACCESS):
partner-granted repos are audited regardless of visibility (a partner's
eyes make the tree exposed), carry a names-only Actions-secrets zero-
policy (RED on any repo secret — a push collaborator can exfiltrate via
a workflow edit; re-home is L-PARTNER-GRANTS work), and cite guard-owed
when granted without a moat-guard entry. --require-guard makes the
evict-then-guard end-state an executable predicate for the two seeded
CONST-*-MOAT board tasks. estate.yaml classes both shared private repos
operation_private so protection posture applies (was protection-exempt
private_unreviewed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@4444J99, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5643fa0e-3278-49b0-acf1-bbed13bc608e

📥 Commits

Reviewing files that changed from the base of the PR and between 9bdd878 and b59cb83.

📒 Files selected for processing (3)
  • institutio/github/estate.yaml
  • organs/consulting/constellation/seed-tasks.py
  • scripts/moat-audit.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/moat-partner-hardening

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.

@github-actions

Copy link
Copy Markdown

Multi-agent review roll call
@codex review

(CodeRabbit and Claude review automatically. Reviewers: post substantive findings only. Authors/agents: address every thread, push fixes to this branch, reply and resolve, then re-request review.)

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Comment thread scripts/moat-audit.py Fixed
CodeQL taints anything returned by the /actions/secrets endpoint, so
even printing the count flags py/clear-text-logging-sensitive-data.
Posture is selected by branching ('clean'/'exposed'), which is also
the tighter output discipline: nothing derived from the endpoint ever
reaches a log line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@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: d1218b57c9

ℹ️ 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 scripts/moat-audit.py
Comment on lines +82 to +85
res = subprocess.run(
["gh", "api", f"repos/{repo}/actions/secrets", "--jq", ".total_count"],
capture_output=True, text=True,
)

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 Handle missing gh in the secrets probe

When PyYAML successfully marks a repo as granted but the runner does not have gh on PATH, this new subprocess.run([...]) raises FileNotFoundError instead of behaving like repo_visibility, which treats missing GitHub CLI access as unknown. That makes scripts/moat-audit.py --repo <granted> --require-guard crash before it can report guard/leak status, so local or minimal runners without the GitHub CLI cannot execute the new moat predicates unless they remember --no-visibility; catch missing CLI/timeouts and return a skipped/unknown count instead.

Useful? React with 👍 / 👎.

receipt="git:organvm/limen:moat-guard.json",
),
dict(
id="CONST-CANNIBAL-MOAT",

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 Seed moat work for every granted repo

This added block creates --require-guard tasks for only the Jessica and Scott grants, but institutio/github/access.yaml also grants organvm/sovereign-systems--elevate-align, and moat-guard.json has no entry for it. The default audit merely reports that repo in guard_owed and still exits 0 unless --require-guard is run for that specific repo, so the Maddie partner-visible repo never gets a blocking eviction/guard task from this seeder; add the third row or derive these rows from ACCESS.

Useful? React with 👍 / 👎.

Comment thread scripts/moat-audit.py
Comment on lines +70 to +75
try:
import yaml
grants = (yaml.safe_load(ACCESS.read_text(encoding="utf-8")) or {}).get("grants") or {}
return {str(r) for r in grants}
except Exception:
return set()

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 Badge Do not silently drop granted repos without PyYAML

If PyYAML is unavailable or the import fails, this broad except returns an empty grant set, so every new partner-specific guard in this change is bypassed: granted private repos are not scanned, guard_owed stays empty, and the secrets zero-policy is never checked. moat-audit.py previously ran with only stdlib dependencies, so minimal/local predicate runners can now report green while ignoring ACCESS entirely; fail loudly when ACCESS exists but cannot be parsed, or add a stdlib fallback for this simple grants mapping.

Useful? React with 👍 / 👎.

Comment thread scripts/moat-audit.py
Comment on lines +86 to +87
if res.returncode != 0:
return None

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 Fail closed when secret counts are unreadable

For a partner-granted repo, a nonzero exit from gh api repos/<repo>/actions/secrets can mean the token lacks permission to list secrets, but this path returns None and the caller treats that the same as zero secrets. In that scenario the new zero-policy check passes even though it never proved the repo has no Actions secrets; unless --no-visibility was explicitly requested, propagate an unreadable/unknown secret count as a failing result instead of excluding it from secrets_exposed.

Useful? React with 👍 / 👎.

Comment thread scripts/moat-audit.py
lure_gaps = [r for r in results if r["lure"] in ("gap", "dark")]
guard_owed = [r for r in results if r["guard_owed"]]
secrets_exposed = [r for r in results if r["repo_secrets"]]
guard_missing = [r for r in results if args.require_guard and not guard_repos.get(r["repo"])]

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 Require real patterns for guard completion

With --require-guard, this only checks that the moat-guard row is truthy, so a repo can satisfy the new CONST-*-MOAT done predicate by adding a row that contains just note or scan_paths and no leak_patterns; scan_leaks() then returns no_patterns with no hits, and the audit passes without asserting any tuned value is absent. For the evict-then-guard tasks, require at least one declared leak pattern before considering the guard present.

Useful? React with 👍 / 👎.

@4444J99
4444J99 added this pull request to the merge queue Jul 23, 2026
Merged via the queue into main with commit 1f93661 Jul 23, 2026
16 checks passed
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