Skip to content

fix(redact): see the annotations this document has added, not only the file's - #69

Merged
tannevaled merged 1 commit into
mainfrom
fix/redact-sees-pending-annotations
Nov 7, 2026
Merged

tannevaled merged 1 commit into
mainfrom
fix/redact-sees-pending-annotations

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Follows #68 (v0.28.0).

The gap

Doc.Redact refuses a region holding an annotation, because an annotation's own
/Contents can hold the very words being redacted. It read the source
page's /Annots — and a mark or a widget added through Doc.Mark or
Doc.AddFields is held on the Doc until the write, because each names the
page object it sits on and the pages have no object numbers until then.

So neither is in the source at all, and a redaction under one was accepted.

How it was found

The workbench, within a minute of being wired up, in the flow a reader walks
into: highlight a line, then decide to redact it. The text went and the
annotation stayed — with the marked-up words still in the file as that
annotation's own note.

The app's test for "the library's refusal reaches the status line" is what
failed, and it was right to:

the status line says "removed 17 characters from 1 page — the text is gone from
the file, not covered", and not why the redaction was refused

A test written to check that a refusal is passed along found that there was no
refusal to pass.

The fix

Redact now also refuses a region reached by a pending Markup's quads or a
pending field's widget rectangle, saying which to drop first.

⛔ A field's places are its widgets, each with its own page — one field can
show on several pages, so the field is not the thing with a position. That is
why the loop is over f.Widgets and not over f.

Tests

Seven refusals now, each its own subtest. Both new ones check the page-number
guard the way it can actually go wrong: a mark and a widget on page 2,
sitting exactly over the region's coordinates on page 1, must not stop that
redaction — a page number is not a position. And a mark on another line of the
same page is nobody's business either.

393 functions at 100.0% by go tool cover -func; go vet and the full
suite clean.

Still open

The symmetric question for annotations the source file already carries: refusing
is right for one somebody else wrote, but a mark this caller just made is
arguably one to remove along with the text rather than refuse over. That is a
behaviour change worth its own issue, and the refusal names the way out in the
meantime.

🤖 Generated with Claude Code

…e file's

The annotation check read the SOURCE page's /Annots. A mark and a widget
are held on the Doc until the write — each names the page object it sits
on, which has no number until then — so neither is in the source at all,
and a redaction under one was accepted.

The workbench found it within a minute of being wired up, in the flow a
reader walks into: highlight a line, then decide to redact it. The text
went and the annotation stayed, with the marked-up words still in the
file as that annotation's own note. The app's test for "the library's
refusal reaches the status line" is what failed, and it was right.

Doc.Redact now refuses a region that a pending Markup's quads or a
pending field's widget rectangle reaches, telling the caller to drop the
mark or the field first. A field's places are its WIDGETS, each with
its own page: one field can show on several pages, so the field is not
the thing with a position.

Seven refusals now, each its own subtest, and the page-number guards are
tested with a mark and a widget sitting on page 2 exactly over the
region's coordinates on page 1 — a page number is not a position.

393 functions at 100.0%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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