chore(canary-phase4): docx generator complete
Phase 4 ships the third generator in the canary registry. docx canary
tokens are produced by zip-patching a committed template.docx — the
HONEY_TRACK_URL placeholder in word/footer2.xml's INCLUDEPICTURE field
is replaced at Generate time with the canary's /c/{id} trigger URL.
Per-entry zip Method (STORE/DEFLATE) is preserved so Word/LibreOffice
still opens the document. Trigger is shared with webbug (spec §9.3
line 1118): 200 + 43-byte transparent GIF + cache headers; nil-token
returns the same response per spec §8.5 defense-in-depth.
Implementation commits:
f36cce9a feat(canary): docx template (binary blob + build helper)
82bb3a9f feat(canary): docx generator (zip-patch INCLUDEPICTURE)
5884f986 feat(canary): register docx generator in registry
Audit (two agents in parallel; spec §9.3 + §8.5):
superpowers:code-reviewer PASS — 0 BLOCKER / 0 SHOULD-FIX / 3 NIT
general-purpose (spec adherence) PASS — 0 SPEC-VIOLATION, 6/6 invariants MATCH
Cleared in-phase via 10ae118d (fix(canary-phase4): address audit nits
before rollup):
N1 — added 'RemoteAddr loopback IPv6 [::1]:9999' + 'XFF IPv6 rightmost'
subtests to docx generator_test.go for symmetry with webbug
N2 — renamed shadowed cErr to hErr in patchTemplate's loop body
N3 — newDocxToken helper sets Memo/Type matching webbug's pattern;
not actionable (stylistic positive)
Decisions baked in this phase (anti-relitigation):
- Spec §9.3 Filename example (`if t.Filename == ""`) does not compile
against the actual schema — Token.Filename is *string per entity.go:52.
resolveFilename safely deref's, trims, and falls back to 'Document.docx'
for nil / empty / whitespace pointers.
- Spec example does not propagate rc.Close() after io.ReadAll — the
implementation does, ordered so a read error wins over a close error
(required by .golangci.yml errcheck.check-blank: true).
- cmd/builddocxtemplate is a pure-Go OOXML builder rather than the
spec's suggested LibreOffice/python-docx workflow. Matches the
Phase 5 cmd/buildpdftemplate precedent in the implementation plan.
Lives at cmd/builddocxtemplate (excluded from the production binary).
- cmd helper uses filepath.Clean(out) before os.OpenFile to satisfy
gosec G304 on an operator-supplied -out flag — no //nolint pragma
(banned by project rule).
State after Phase 4:
Registered generators: 3 (webbug, slowredirect, docx)
Pending generators: 4 (pdf, kubeconfig, envfile, mysql)
BACKLOG.md open section: still empty
Pre-audit gate: BUILD/VET/unit/integration/lint clean across backend
Manual smoke (Task 4.6) is operator-deferred: open a generated docx
in LibreOffice with a network monitor and confirm the GET to /c/{id}
fires when the document opens. Not blocking phase rollup.
Phase 5 next: cmd/buildpdftemplate + pdf generator with byte-padded
HONEY_TRACK_URL_PADDED_…_76 placeholder in an /AA /O /URI action.
This commit is contained in:
parent
10ae118d53
commit
0e47274525