Skip to content

feat(selfhost): add container-private per-repo config dir - #1390

Merged
JSONbored merged 1 commit into
mainfrom
feat/selfhost-private-config
Jun 25, 2026
Merged

feat(selfhost): add container-private per-repo config dir#1390
JSONbored merged 1 commit into
mainfrom
feat/selfhost-private-config

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

A self-host operator could only set per-repo review policy via the repo's public .gittensory.yml — which contributors can read, and whoever can see the gate thresholds, autonomy, or label policy can game them. This adds a private alternative that lives in the container.

  • GITTENSORY_REPO_CONFIG_DIR — mount a dir and drop one {owner}__{repo}.{yml,yaml,json} per repo (lowercased slug, /__, e.g. jsonbored__metagraphed.yml). When a file exists for a repo, the focus-manifest loader reads it instead of fetching the public .gittensory.yml.
  • Private by construction: read fresh from local fs each review (edits apply immediately), tagged api_record (which the existing public-only preview path already excludes), and never persisted — so it can't leak into contributor-facing previews or the snapshot cache.
  • Workers-safe: the fs reader is a Node-only closure injected once at boot via setLocalManifestReader (server.ts); the shared loader never imports node:fs. Unset dir ⇒ null reader ⇒ byte-identical public-fetch behavior (cloud unaffected).
  • Reuses the existing manifest schema, so the private file controls gate, autonomy, labels, and model/effort with zero new schema.

No issue linked — self-host hardening surfaced while bringing the brokered self-host online; lets metagraphed's gate/autonomy/labels be configured privately.

Scope

  • src/selfhost/private-config.ts (new) — Node-only {owner}__{repo} reader over the config dir
  • src/signals/focus-manifest-loader.tssetLocalManifestReader hook + the private-first branch (Workers-safe)
  • src/server.ts — register the reader at boot from GITTENSORY_REPO_CONFIG_DIR
  • src/env.d.ts, docs/self-hosting.md — document the var
  • test/unit/private-config.test.ts (new) + test/unit/focus-manifest-loader.test.ts — reader + loader-branch coverage

Validation

  • npm run test:ci — green (4433 passed; typecheck, coverage, workers, mcp, ui:*)
  • Patch coverage: private-config.ts 100% branch (8/8); loader private-branch covered (prefers reader, falls through on null, skips on publicOnly). The publicOnly-preview test asserts the private reader is never consulted.

Safety

  • No secrets/tokens/wallets/scores in code, tests, or docs.
  • node:fs is confined to the self-host Node entry (server.ts already imports node:fs); the shared loader stays Workers-safe via injection.
  • Default-off: unset GITTENSORY_REPO_CONFIG_DIR ⇒ no behavior change; cloud is byte-identical.

A self-host operator could only configure per-repo review policy via the
repo's public .gittensory.yml, which contributors can read — and whoever can
see the gate thresholds, autonomy, or label policy can game them. Add
GITTENSORY_REPO_CONFIG_DIR: when set, the focus-manifest loader reads a mounted
{owner}__{repo}.{yml,yaml,json} INSTEAD of fetching the public file, so policy
stays private and never appears in contributor-facing previews. The reader is a
Node-only closure injected at boot via setLocalManifestReader, keeping the
shared loader Workers-safe; unset ⇒ byte-identical public-fetch behavior.
@dosubot dosubot Bot added the size:M label Jun 25, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.33%. Comparing base (ce5fa5e) to head (740c5ea).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1390   +/-   ##
=======================================
  Coverage   95.33%   95.33%           
=======================================
  Files         191      192    +1     
  Lines       20734    20750   +16     
  Branches     7495     7500    +5     
=======================================
+ Hits        19767    19783   +16     
  Misses        383      383           
  Partials      584      584           
Files with missing lines Coverage Δ
src/selfhost/private-config.ts 100.00% <100.00%> (ø)
src/signals/focus-manifest-loader.ts 98.93% <100.00%> (+0.05%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit 6138b9e into main Jun 25, 2026
19 checks passed
@JSONbored
JSONbored deleted the feat/selfhost-private-config branch June 25, 2026 21:30
@github-actions github-actions Bot mentioned this pull request Jun 26, 2026
12 tasks
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