Files
tessera-ctl/.planning/quick/261009-ikt-cert-manager-umbau-mehrere-dateien-zip-f/261009-ikt-VERIFICATION.md
T
schalli 76a30458fc docs(quick-261009-ikt): Cert-Manager-Umbau
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 17:12:10 +02:00

78 lines
8.0 KiB
Markdown

---
phase: quick-261009-ikt
verified: 2026-10-09T16:40:00Z
status: passed
score: 9/9 must-haves verified
covered_files:
- .planning/quick/261009-ikt-cert-manager-umbau-mehrere-dateien-zip-f/261009-ikt-PLAN.md
- .planning/quick/261009-ikt-cert-manager-umbau-mehrere-dateien-zip-f/261009-ikt-SUMMARY.md
- apps/api/src/cert-manager/cert-aia.ts
- apps/api/src/cert-manager/cert-chain.ts
- apps/api/src/cert-manager/cert-output.ts
- apps/api/src/common/public-url-guard.ts
covered_digest: "v3:sha256:37fd7e62185dc46fa1ca7614efb6287503b7d9b803e857a1f4818008b9547ee6"
behavior_unverified: 0
overrides_applied: 0
re_verification: false
---
# Quick 261009-ikt: Cert Manager Umbau - Verification Report
**Goal:** One upload tab (files, ZIPs, pasted PEM) as a shared working set for all other tabs; "second file overwrites first" fixed; chain building plus Fullchain (root optional, default off); all common formats in and out incl. EC; PFX output (3DES default, AES option); target-system templates; "Fehlendes Zertifikat holen" on button only, SSRF-safe; module 1.2.0, module changelog, CHANGELOG, guides.
**Status:** passed
**Re-verification:** No, initial verification
## Independent evidence (not taken from SUMMARY.md)
| Check | Command | Result |
|-------|---------|--------|
| API unit tests | `vitest run src/cert-manager src/common src/module-registry` (apps/api) | 20 files, 559 tests green (cert-aia 26, public-url-guard 51, cert-output 47, cert-keys 39, cert-templates 25, cert-pkcs12 22, zip-expand 15 ...) |
| Web tests | `vitest run modules/cert-manager src/messages` (apps/web) | 13 files, 150 tests green (incl. umlaut/messages guard) |
| Type check | `tsc --noEmit` api and web | both exit 0 |
| Live e2e on the running stack | `e2e/e2e-cert.sh all` | `files`, `fullchain`, `zip`, `inputs`, `formats`, `templates`, `version`, `aia` all ok. openssl reads outputs: pkcs12 compat = `pbeWithSHA1And3-KeyTripleDES-CBC`, modern = `PBES2 AES-256-CBC`, IIS template (RSA and EC) = 3DES, p7b/p7c `print_certs` lists the full chain. Live AIA fetch obtained YE2 from ye2.i.lencr.org and reported the next missing level (Root YE) |
| Old forge cert parsers gone | grep `certificateFromPem/Asn1`, `certificationRequestFrom*`, `pkcs7.messageFrom*` in non-spec api code | no hits |
| Old routes gone | controller exposes only `analyze`, `build`, `fetch-issuer`; e2e setup asserts `POST parse` = 404 (passed) | ok |
| Debt markers | grep TBD/FIXME/XXX in module code (api + web, non-test) | none |
| UI evidence | viewed `.playwright-mcp/cert-manager/ikt-dark-files.png` | Single "Dateien" tab with 4 entries (two separate selections plus ZIP per contained path without __MACOSX, plus unlocked PFX), per-entry "Entfernen", browser-window-only notice, tabs Analysieren/Aufteilen/Zusammenführen/Konvertieren/Vorlagen. 13 dark/light proof images present |
## Observable Truths
| # | Truth | Status | Evidence |
|---|-------|--------|----------|
| 1 | "Dateien" tab: several files/ZIP stay in list (no overwrite), per-row recognition, per-ZIP-path, junk skipped, remove buttons, pasted PEM, browser-only notice | VERIFIED | FilesTab.tsx is the only component with a file input; screenshot shows the behaviour; e2e files/zip ok; zip-expand spec 15 tests (limits, nested, encrypted) |
| 2 | Other tabs have no own upload; empty set points to "Dateien" | VERIFIED | grep for file inputs: only FilesTab (and PfxOptions matched on an unrelated pattern for `compat`/`modern`, not a file input); EmptyWorkspace component present; page tests green |
| 3 | Merge orders chain itself (issuer + real signature check), Fullchain / Nur Kette, root only when ticked (default off), gaps reported, API re-builds order | VERIFIED | MergeTab `includeRoot` default `false`; `buildChains` uses `checkIssued` + `verify` (decoy fixture with same name/SKI covered in cert-chain spec); `buildOutput` calls `buildChains`; e2e fullchain: openssl verify OK, wrong order + foreign inter gives exactly 2 blocks, 3 with root, gap reported |
| 4 | RSA and EC in all common input formats (PEM/DER, PKCS#7, PKCS#12 incl. 3DES/RC2/modern, keys PKCS#1/8/SEC1 enc/unenc, CSR), matching, password per file | VERIFIED | model/keys/pkcs12/csr specs green (39 + 22 + 7 tests plus model/analyze); 47 generated fixtures incl. EC and legacy PFX; e2e inputs ok; `parsePasswords` in controller |
| 5 | Outputs: cert PEM/DER/p7b/p7c, Fullchain/Kette in PEM/p7b/p7c, cert+key PEM, PFX compat (default) / modern, key formats with optional password, CSR PEM/DER; openssl reads all | VERIFIED | PfxOptions default `compat`; e2e formats shows openssl pkcs12 -info algorithms and pkcs7 -print_certs; cert-output spec 47 tests; build DTO `pfxEncryption: 'compat' | 'modern'` |
| 6 | Vorlagen: Nginx, Apache >=2.4.8, Apache older, IIS (PFX compat), NPM, HAProxy, Tomcat; explain when key missing | VERIFIED | cert-templates.ts/spec (25 tests); TemplatesTab; e2e templates ok (IIS = 3DES for RSA and EC); screenshot per SUMMARY ikt-dark-templates.png exists |
| 7 | "Fehlendes Zertifikat holen" only on click, server reads URL from cert, public addresses only, ports 80/443, hardened guard, per-hop re-check and connect-time lookup guard, 8 s / 256 KiB, issuer verification, added as "nachgeladen von {host}" | VERIFIED | `fetchIssuer(cert.pem)` called only in ChainView click handler (`onClick={click}`); DTO carries only `pem`; cert-aia.ts: `AIA_TIMEOUT_MS=8000`, `AIA_MAX_BYTES=256*1024`, `redirect:'manual'`, max 3 hops, `createGuardedLookup` in undici Agent, standard-port-only check, fingerprint/issuer verification; public-url-guard expands IPv6 to 8 groups (mapped hex, NAT64, 6to4, Teredo ...) with 51 spec tests; live e2e fetched YE2 from the real letsencrypt chain |
| 8 | No key/password storage or logging; old routes/service gone; module 1.2.0 (2026-10-09), module changelog, CHANGELOG incl. guard security fix, three guides updated; screenshots | VERIFIED | Only logger call with data is a warn with hosts and error code (no PEM/passwords); changelog top entry `1.2.0` / `2026-10-09`, seed uses `latestVersion(CERT_MANAGER_CHANGELOG)`, e2e version ok; CHANGELOG "Unveröffentlicht" has 3 new entries plus "Sicherheit" guard fix and EC fix; docs diff: anwender +25, betrieb +10, entwicklung +105; module-changelog spec green; images present |
| 9 | `build` has own 512 KiB JSON parser with coded 413 / 400; other routes keep 100 kB; global parser active; each task leaves a usable module | VERIFIED | `app.use(CERT_BUILD_ROUTE, certBuildJsonBody, certBuildBodyErrors)` in main.ts; cert-json-body spec 5 tests; e2e fullchain covers 600 KiB to 413 tooLarge, bad JSON to 400, login 150 kB to 413; seven task commits each present in git log (75ea83f, 30118a2, 1554ae8, fcac0a3, 65a1dca, 47b2621, a2fc2cb) |
**Score:** 9/9 truths verified, 0 behavior-unverified (each state/ordering invariant has a passing spec and a live e2e section).
### Requirements Coverage
| Requirement | Status | Evidence |
|-------------|--------|----------|
| QUICK-261009-ikt | SATISFIED | All truths above |
### Anti-Patterns Found
None blocking. Notes (info only):
- Web upload caps are stricter than the API (web 10 MiB total vs API 20 MiB); intentional, pre-checks only.
- SUMMARY records one flaky unrelated test (`domains-page.test.tsx`), not part of this task.
### Human Verification
Not required for status. Real-environment checks the SUMMARY already lists for the user after pulling to alpha (not goal blockers, they need infrastructure this verifier cannot reach): NPM accepting `certificate.pem`/`intermediate.pem`/`privkey.pem` (EC key header), importing the compat PFX on a real Windows Server, outbound ports 80/443 from the alpha api container, and favicon/Nextcloud-logo loading under the stricter shared guard.
## Gaps Summary
No gaps. The goal is achieved in the codebase: tests, type checks and the live e2e suite (including a real AIA fetch) pass on an independent run, the old routes and forge certificate parsers are removed, and changelog/docs/version are in place. Planning-only files (the todo move, this task directory) remain uncommitted by design.
---
_Verified: 2026-10-09_
_Verifier: Claude (gsd-verifier)_