mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 22:48:57 +02:00
fix(code-intelligence): gbrain search/export are consent-gated and receipted
The Sourcebot side got this in the last round; gbrain had the same hole — search() and export() sent repo-derived query text into a possibly-remote DATABASE_URL with no consent check and no egress receipt, bypassing the deny-tier veto. Both now assert consent before any bytes move, receipts record the actual consent state (never a hardcoded true), and search receipts carry the query's sha256. gbrain stays fail-closed: the adapter cannot see where DATABASE_URL points, so every send requires consent. 7 new tests, red-first.
This commit is contained in:
@@ -224,6 +224,16 @@ async function cmdSearch(terms: string[]): Promise<void> {
|
||||
// loopback providers need no consent, so their path is unchanged.
|
||||
const searchRoot = getRoot(provider!.id) ?? resolve(process.cwd());
|
||||
const consented = hasConsent(searchRoot, undefined, "read");
|
||||
// Honest pre-flight (mirrors cmdIndex): the adapter enforces the same gate
|
||||
// (assertEgressConsent throws PROVIDER_NOT_CONSENTED before any bytes or
|
||||
// receipt exist), but the CLI names WHY — missing consent vs a deny repo
|
||||
// trust policy — instead of surfacing a generic provider error.
|
||||
if (!provider!.local && !consented) {
|
||||
const recorded = readSelection().consents[searchRoot] === true;
|
||||
fail(recorded
|
||||
? `${provider!.label} search is blocked by the repo trust policy (deny — the query text is repo-derived content). Change with: gstack-gbrain-repo-policy set <origin-url> read-only (search allowed) or read-write`
|
||||
: `${provider!.label} would send the query text (repo-derived content) off this machine. Run \`gstack-code-intelligence consent ${searchRoot} yes\` first.`);
|
||||
}
|
||||
try {
|
||||
const hits = await provider!.search(query, { limit: 10, consented });
|
||||
if (!hits.length) {
|
||||
|
||||
Reference in New Issue
Block a user