v1.88.1.0 fix: harden credential boundaries and owned state (#2942)

* fix(settings): preserve symlinked settings targets

Resolve the selected target for locking, mutation, backup, and rollback; refuse target changes and preserve private modes. Addresses #2830.

* fix(redact): bind masking to original detected spans

Inspired by #2929's anchored-span diagnosis; independently implemented using normalization offsets. Addresses #2930 and the relocation portion of #2912 without changing detection sensitivity.

* fix(evals): exclude operator credentials from prefix admission

Adapts the credential-suffix screen proposed in #2636, with real launched-child regression coverage and deliberate provider-auth exceptions.

* fix(artifacts): retain custom allowlist rules on reinitialization

Preserve the exact user-owned suffix and publish only a successfully assembled replacement. Independently implements the repair reported in #2907.

* test(cso): verify exact masked reads and unmaskable payload refusal

* fix(cso): preserve exact filesystem identities through lease recovery

Preserve 64-bit device/inode identity and nanosecond race checks. Add native NTFS lifecycle coverage for #2927; retain ambiguous legacy-state refusal without claiming Windows PID-reuse recovery is resolved.

* fix(redact): bind pre-push scans to destination and preserve seam context

Uses #2935 (bd07318) as source evidence for push-target range and slice-overlap defects. Independently implemented; no cherry-pick or release metadata adoption.

* test(ci): gate native agent ownership and settings links on macOS

* fix(browse): bind agent lifetimes and cleanup to owned generations

Uses #2931 by Chris Hutton / Claude Fable 5.1 as attributed design input; independently implemented without broad sweeps or copied code. Keep uncertain children and locks rather than deleting foreign state.

* test(ci): include concurrent shutdown controls in the native macOS gate

* v1.88.1.0 fix: harden credential boundaries and owned state

* fix(redact): preserve target provenance and scan boundary semantics

* test(artifacts): read managed rules from atomic allowlist assembly

* fix: preserve native exit observations and fixture prerequisites

* fix: preserve UTF-16 offsets through redaction normalization
This commit is contained in:
Garry Tan
2026-09-23 08:54:53 -04:00
committed by GitHub
parent 636175d349
commit b9706f3635
42 changed files with 2719 additions and 339 deletions
+5 -5
View File
@@ -5,9 +5,9 @@ import * as path from "path";
const ROOT = path.resolve(import.meta.dir, "..");
const INIT = fs.readFileSync(path.join(ROOT, "bin", "gstack-artifacts-init"), "utf-8");
/** Pull a quoted heredoc body out of gstack-artifacts-init by target filename. */
/** Pull a quoted heredoc body out of gstack-artifacts-init by destination. */
function heredoc(target: string): string {
const re = new RegExp(`cat > "\\$GSTACK_HOME/${target}" <<'EOF'\\n([\\s\\S]*?)\\nEOF\\n`);
const re = new RegExp(`cat > "${target}" <<'EOF'\\n([\\s\\S]*?)\\nEOF\\n`);
const m = INIT.match(re);
if (!m) throw new Error(`heredoc for ${target} not found in gstack-artifacts-init`);
return m[1];
@@ -39,7 +39,7 @@ const DECISION_PATHS = [
* Windows -- which is the platform where this bug bit.
*/
describe("the artifacts allowlist covers the decision store", () => {
const globs = heredoc("\\.brain-allowlist")
const globs = heredoc("\\$ALLOWLIST_TMP")
.split("\n")
.map((l) => l.trim())
.filter((l) => l && !l.startsWith("#"));
@@ -51,7 +51,7 @@ describe("the artifacts allowlist covers the decision store", () => {
});
test("decisions.* are class artifact, so they sync in artifacts-only mode too", () => {
const map = JSON.parse(heredoc("\\.brain-privacy-map\\.json"));
const map = JSON.parse(heredoc("\\$GSTACK_HOME/\\.brain-privacy-map\\.json"));
for (const p of DECISION_PATHS) {
const hit = map.find((e: { pattern: string; class: string }) => globToRe(e.pattern).test(p));
expect({ p, cls: hit?.class }).toEqual({ p, cls: "artifact" });
@@ -61,6 +61,6 @@ describe("the artifacts allowlist covers the decision store", () => {
test("the allowlist still ends with the user-additions marker", () => {
// Additions below it survive re-init; a glob added above would be silently
// overwritten the next time gstack-artifacts-init runs.
expect(heredoc("\\.brain-allowlist").trimEnd()).toMatch(/# ---- USER ADDITIONS BELOW ----/);
expect(heredoc("\\$ALLOWLIST_TMP").trimEnd()).toMatch(/# ---- USER ADDITIONS BELOW ----/);
});
});