Skip to content

chore: recall consolidate defense-in-depth hardening (child re-clamp, NULL-lineage guard, timeout count accuracy)#184

Merged
edheltzel merged 1 commit into
mainfrom
worktree-issue-145-consolidate-hardening
Jun 25, 2026
Merged

chore: recall consolidate defense-in-depth hardening (child re-clamp, NULL-lineage guard, timeout count accuracy)#184
edheltzel merged 1 commit into
mainfrom
worktree-issue-145-consolidate-hardening

Conversation

@edheltzel

Copy link
Copy Markdown
Owner

Optional defense-in-depth hardening surfaced by the #141 (PR #144) review + RedTeam gate. None blocked the merge; all three tracked items addressed. risk:low, surgical, no behavior change on the legit path.

What shipped

  1. Child re-clamps newImportance (chore: recall consolidate defense-in-depth hardening (child re-clamp, NULL-lineage guard, timeout count accuracy) #145.1) — the demote UPDATE now uses SET importance = MAX(1, MIN(importance, CAST(? AS INTEGER))). A demote can only ever lower importance, so a directly-piped payload can't raise a record; the absolute floor of 1 is re-pinned regardless of the supplied value. On the legit path (planner always sends the floor) the result is identical to before.

  2. NULL-lineage guard (chore: recall consolidate defense-in-depth hardening (child re-clamp, NULL-lineage guard, timeout count accuracy) #145.2)applyConsolidation now throws loudly if loa_entries is missing the provenance/source_ids columns (guaranteed by migration 13, feat(db): migration 12→13 — source-lineage column for derived consolidation summaries (Phase B prereq of #53) #140) instead of silently writing NULL lineage on an unmigrated/corrupt schema. The main() catch surfaces it as a clean error; the conditional column branching is gone.

  3. Timeout count accuracy (chore: recall consolidate defense-in-depth hardening (child re-clamp, NULL-lineage guard, timeout count accuracy) #145.3) — the child emits cumulative {written, demoted} to stderr after each committed cluster (unique marker prefix). On subprocess timeout the parent recovers the last marker from captured stderr, so the summary reports work actually committed before SIGTERM instead of 0/0. runConsolidate prints a "Partial progress before failure" line when counts are non-zero. Degrades gracefully to the old 0/0 if no marker is captured.

DRY / conventions

  • Hooks still never import from src/; the stderr marker contract is restated on both sides with cross-referencing comments, following the existing ConsolidateApplyResult restatement precedent.
  • Changes are surgical — every line traces to one of the three items.

Verification

  • bun run lint (tsc --noEmit) clean.
  • bun test green: 1182 pass / 0 fail.
  • Added tests: re-clamp can't raise / re-pins floor; missing-column guard throws; onProgress emits cumulative per-cluster totals; parseConsolidateProgress (last-marker, prefixed-line, malformed/none); parent surfaces partial progress on apply error.

Closes #145

- Child re-clamps the demote target via MAX(1, MIN(importance, ...)) so a
  directly-piped payload can only lower importance, never raise it, and the
  absolute floor of 1 is re-pinned regardless of the supplied value.
- Fail loudly when loa_entries lacks provenance/source_ids columns instead of
  silently writing NULL lineage on an unmigrated schema (guaranteed by #140).
- Child emits cumulative progress to stderr after each committed cluster; the
  parent recovers committed counts on subprocess timeout so the summary no
  longer under-reports work that landed before SIGTERM.

Closes #145
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.

chore: recall consolidate defense-in-depth hardening (child re-clamp, NULL-lineage guard, timeout count accuracy)

1 participant