From 7ff6c05f4f92ee2cd3279eb01be137b5b9a7d0a3 Mon Sep 17 00:00:00 2001 From: maruson08 Date: Thu, 27 Aug 2026 18:46:45 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=84[Docs]=20Reorganize=20project=20doc?= =?UTF-8?q?umentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + README.md | 432 ++++-------------------------------------- README.original.md | 1 - docs/README.md | 23 +++ docs/architecture.md | 72 +++++++ docs/dependencies.md | 25 +++ docs/privacy-model.md | 42 ++++ docs/tool-status.md | 81 ++++++++ docs/v2-release-qa.md | 10 +- 9 files changed, 292 insertions(+), 395 deletions(-) delete mode 100644 README.original.md create mode 100644 docs/README.md create mode 100644 docs/architecture.md create mode 100644 docs/dependencies.md create mode 100644 docs/privacy-model.md create mode 100644 docs/tool-status.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 1176398..7189542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Narrowed homepage and category privacy copy to production file-content processing and localized shared navigation and summary accessible names across all six interface languages. - Added a live v2 promotion QA matrix that keeps blocked browser evidence separate from passing automated checks. - Recorded completed manual Chrome release QA and verified EXIF Orientation preservation, advancing the documented v2 status to READY FOR PROMOTION without creating a release. +- Reorganized project documentation around a concise README and focused architecture, privacy, dependency, tool-status, and audit references. - Removed the standalone planned Rotate PDF card; page rotation remains available as part of PDF Organizer. - Moved shared browser image validation and decoding into `tools/shared/image.js` for PDF and Image tools. diff --git a/README.md b/README.md index c394dac..f995931 100644 --- a/README.md +++ b/README.md @@ -1,346 +1,47 @@ # Secure Tools -Secure Tools is a privacy-first web hub for everyday file utilities. Production tools process file contents locally in the browser instead of uploading them to a server. +Secure Tools is a privacy-first suite of browser utilities for everyday PDF and image work. Production tools process file contents on the user's device instead of sending them to an upload service. -The project uses a category-first architecture, pull-request CI plus `main`/`v2` integration CI gates, and static GitHub Pages deployment. +The project is a static, category-first web application with no account requirement, backend, database, analytics, advertising, or telemetry. -The v1 baseline is recorded in the [changelog](./CHANGELOG.md) and historical [v1.0.0 release QA checklist](./docs/release-qa.md). The live [v2 promotion QA gate](./docs/v2-release-qa.md) records automated evidence, manual browser results, dependency and repository risks, and current promotion readiness. +## Core principles -## Available tools - -- [Image Converter](./tools/image/converter/) — convert batches of JPEG, PNG, and WebP images locally with predictable names and ZIP output. -- [Image Resize](./tools/image/resize/) — resize image batches by pixels or percentage while preserving aspect ratio by default. -- [Image Compressor](./tools/image/compress/) — quality-compress image batches locally and compare original and result sizes. -- [Image Metadata Inspector & Cleaner](./tools/image/metadata/) — inspect supported metadata and save a fail-closed, verified cleaned copy without pixel re-encoding. -- [Images to PDF](./tools/pdf/images-to-pdf/) — arrange JPEG, PNG, and WebP images and save them as one PDF. -- [Merge PDF](./tools/pdf/merge/) — validate, order, and combine PDF pages without rasterizing them. -- [Split PDF](./tools/pdf/split/) — extract ordered page ranges or create predictable per-page and fixed-interval archives. -- [Organize PDF](./tools/pdf/organize/) — preview, reorder, rotate, remove, and export pages without rasterizing them. -- [PDF to Images](./tools/pdf/to-images/) — convert ordered pages to PNG, JPEG, or WebP files and local ZIP archives. -- [PDF Metadata Inspector & Cleaner](./tools/pdf/metadata/) — inspect supported document-info fields and save a locally verified cleaned copy. - -The homepage and category hubs clearly distinguish production tools from planned work. - -## Privacy metadata hub - -[`/tools/privacy/`](./tools/privacy/) is a navigation hub for the two existing production metadata tools. It does not add a generic inspector, cleaner, parser, or processing engine. - -- Image files route to [Image Metadata Inspector & Cleaner](./tools/image/metadata/), whose documented scope covers supported JPEG, PNG, and WebP structures. Its successful inspection may still be partial and non-exhaustive. -- PDF files route to [PDF Metadata Inspector & Cleaner](./tools/pdf/metadata/), whose cleaning scope is limited to supported document-info fields and does not claim to remove every XMP packet, attachment, annotation, or hidden structure. - -Both tools process file contents locally and verify only their documented supported scope. Scan/OCR and Media remain planned categories with non-interactive cards. - -## Interface languages - -Secure Tools ships complete, same-origin interface catalogs for: - -- English (`en`) -- 한국어 (`ko`) -- 日本語 (`ja`) -- Español (`es`) -- Deutsch (`de`) -- Français (`fr`) - -The first visit resolves a supported browser locale by its primary language subtag, so values such as `ja-JP`, `es-MX`, `de-DE`, `fr-CA`, and `ko-KR` select the matching catalog. Unsupported languages fall back to English. A manual selection is stored locally and takes precedence on later visits. Each switch updates visible copy, accessibility labels, document metadata, and the document's `` value without reloading or resetting tool state. - -Locale modules are bundled with the static site. Secure Tools does not call a translation API, download runtime locale data, or add a remote font dependency. Metadata dates continue to use the selected document language through `Intl.DateTimeFormat`. - -The [i18n copy-review record](./docs/i18n-copy-review.md) documents the source-level Korean review and the checks applied to new catalogs. These translations have not been certified by professional native-language reviewers. - -## Privacy principles - -- File contents are processed on the user's device by production tools. -- Basic utilities do not require an account. -- The web hub includes no analytics, behavioral tracking, advertising, or tracking pixels. -- Theme and language preferences are the only values stored in `localStorage`. -- First-party tool code does not call `fetch`, `XMLHttpRequest`, `WebSocket`, or `sendBeacon`. -- Privacy claims can be checked through source inspection and the browser Network panel. -- External links such as GitHub are governed by the destination service's policies. - -## Architecture - -The hub is a static site built with semantic HTML, CSS, and Vanilla JavaScript ES Modules. It has no framework, build step, backend, database, authentication, runtime API, or required package installation. - -```text -. -├── index.html -├── 404.html -├── about/ -├── privacy/ -├── css/ -│ ├── base.css -│ ├── components.css -│ ├── pages.css -│ ├── categories.css -│ └── secondary.css -├── js/ -│ ├── config.js -│ ├── i18n.js -│ ├── main.js -│ ├── theme.js -│ └── locales/ -│ ├── en.js -│ ├── ko.js -│ ├── ja.js -│ ├── es.js -│ ├── de.js -│ ├── fr.js -│ ├── image-resize.js -│ ├── image-compressor.js -│ ├── image-metadata.js -│ └── privacy-hub.js -├── tools/ -│ ├── shared/ -│ │ ├── file.js -│ │ ├── image.js -│ │ ├── pdf.js -│ │ ├── tool.css -│ │ └── save.js -│ ├── pdf/ -│ │ ├── index.html -│ │ ├── images-to-pdf/ -│ │ ├── merge/ -│ │ ├── split/ -│ │ ├── organize/ -│ │ ├── to-images/ -│ │ └── metadata/ -│ ├── image/ -│ │ ├── index.html -│ │ ├── converter/ -│ │ ├── resize/ -│ │ ├── compress/ -│ │ └── metadata/ -│ ├── privacy/ -│ ├── scan/ -│ ├── media/ -│ └── image-to-pdf/ -│ └── index.html -├── assets/vendor/ -│ ├── jspdf/ -│ ├── jszip/ -│ ├── pdf-lib/ -│ ├── pdfjs/ -│ └── secure-metadata/ -└── tests/ - ├── ci-foundation.test.mjs - ├── home-structure.test.mjs - ├── image-to-pdf.test.mjs - ├── image-converter.test.mjs - ├── image-metadata.test.mjs - ├── pdf-merge-and-categories.test.mjs - ├── pdf-split.test.mjs - ├── pdf-metadata.test.mjs - ├── typography-i18n-layout.test.mjs - └── run-all.mjs -``` - -`js/main.js` initializes shared theme and internationalization behavior. `js/theme.js` owns Light, Dark, and System selection, OS color-scheme observation, and persistence. `js/i18n.js` resolves all six supported languages from browser preferences, applies `data-i18n` bindings without reloading, updates metadata and ``, and gives persisted manual selection precedence. Repository links are centralized in `js/config.js`. - -The concise [UX consistency audit](./docs/ux-consistency-audit.md) records the shared interaction patterns, category-first homepage follow-up, multilingual typography policy, resolved drift, and intentional tool-specific exceptions established before v1.0.0 hardening. - -The category hubs are: - -- `/tools/pdf/` -- `/tools/image/` -- `/tools/privacy/` -- `/tools/scan/` -- `/tools/media/` - -Categories are the stable navigation layer. PDF, Image, and Privacy link to production tools; Scan/OCR and Media remain planned and non-interactive. Individual utilities can be added beneath categories without turning the homepage into an unstructured tool list. - -`/tools/image-to-pdf/` is a lightweight static migration page with a meta refresh and visible fallback link to `/tools/pdf/images-to-pdf/`. It does not use JavaScript to redirect. - -## Image Converter - -Image Converter is available at `/tools/image/converter/`. - -- Accepts signature-validated JPEG, PNG, and WebP files and converts one or many sources sequentially with browser-native decode, canvas, and encode APIs. -- Supports JPEG, PNG, and WebP output. JPEG and WebP expose a 50–100% lossy quality control; PNG hides that irrelevant setting. -- Uses explicit browser orientation handling so normally displayed camera images are rendered in their intended orientation. -- Flattens transparent pixels onto white for JPEG while PNG and WebP keep the canvas alpha channel. -- Canvas re-encoding does not preserve EXIF or other embedded image metadata. The tool intentionally makes no configurable metadata-cleaning or preservation claim. -- Replaces supported source extensions, preserves Unicode, limits output bases to 120 characters and 180 UTF-8 bytes, and adds deterministic suffixes for collisions. -- Saves one converted image directly or packages multiple outputs into `converted_images.zip` with the existing same-origin JSZip build. -- Reuses the existing 50 MiB file, 100-file queue, 500 MiB queue, 16,384-pixel dimension, and 50-megapixel per-image limits, plus a 200-megapixel aggregate decoded-work limit per conversion. -- Keeps queued sources available after cancellation or recoverable decode, encode, archive, and save failures so the job can be retried without reloading. - -## Image Resize - -Image Resize is available at `/tools/image/resize/` on the v2 integration branch. - -- Accepts signature-validated JPEG, PNG, and WebP images and processes batches sequentially without uploading file contents. -- Supports pixel bounding dimensions and per-source percentage scaling. Aspect ratio is preserved by default, either dimension may remain automatic, and enlargement is disabled by default. -- Supports Original format for mixed batches plus explicit JPEG, PNG, and WebP output. JPEG and WebP use one batch quality setting; PNG does not expose a meaningless quality control. -- Preserves transparency for PNG/WebP and flattens it onto white for JPEG, matching Image Converter. Canvas re-encoding strips EXIF and other embedded metadata. -- Uses `_resized` names with deterministic collision suffixes and the established Unicode character/byte limits. Multiple outputs are packaged in `resized_images.zip`. -- Enforces the shared 50 MiB file, 100-file queue, 500 MiB queue, 16,384-pixel dimension, and 50-megapixel per-image limits, plus a 200-megapixel aggregate output-work limit. -- Keeps the queue available after validation, decode, canvas, encoding, archive, save, or cancellation errors so settings can be corrected and retried. - -## Image Compressor - -Image Compressor is available at `/tools/image/compress/` on the v2 integration branch. - -- Accepts signature-validated JPEG, PNG, and WebP images and preserves their oriented pixel dimensions while processing sequentially in browser memory. -- Defaults to Original format. JPEG and WebP use an explicit 50–100% quality setting; PNG is re-encoded without a fake lossy-quality control, so size reduction may be limited. -- Reports original size, result size, byte difference, and signed percentage change for every file, plus aggregate batch totals. Larger results are kept and labeled as increases rather than savings. -- Preserves alpha for PNG/WebP and flattens transparent pixels onto white for JPEG. Canvas re-encoding strips EXIF and other embedded metadata. -- Uses collision-safe Unicode `_compressed` names and saves multiple outputs as `compressed_images.zip` through the same-origin JSZip dependency. -- Reuses the established input, queue, dimension, 50-megapixel per-image, and 200-megapixel aggregate decoded-work limits. Queues remain available after recoverable failures or save cancellation. -- Performs no target-size search, resizing, cropping, metadata editing, upload, analytics, telemetry, remote codec, or runtime network request. -## Image Metadata Inspector & Cleaner - -Image Metadata Inspector & Cleaner is available at `/tools/image/metadata/` on the v2 integration branch. - -- Accepts exactly one signature-validated JPEG, PNG, or WebP file and enforces the application’s 50 MiB limit before full inspection. -- Uses the manually pinned, same-origin `secure-metadata v0.1.1` browser artifact. No npm package, CDN, runtime GitHub request, or automatic version check is used. -- Shows the local source thumbnail, detected format, size, and a keyboard-accessible remove/reset path. Up to six high-value decoded fields are shown first; all decoded values, opaque containers, coverage, and diagnostics remain available in a native details disclosure. -- Presents `metadata-partial` as successful but non-exhaustive. “No supported metadata detected” is not a claim that the file contains no metadata. -- Privacy Clean calls the library’s authoritative default policy: supported privacy-related EXIF, XMP, IPTC, comments, PNG text metadata, and timestamps are removed while valid JPEG rendering orientation and ICC color profiles are preserved. -- Customize exposes only supported class-level removal controls for the detected format. Unselected supported classes and unknown structures are preserved; individual metadata-value editing is not offered. -- Keeps source bytes unchanged and never decodes pixels, creates Canvas, resizes, converts, changes quality, or re-encodes the image. -- Calls `verifyMetadata` on cleaned bytes and requires a valid result with every policy check passing before saving. Invalid, incomplete, truncated, or mismatched results fail closed with no output write. -- Derives MIME and the normalized `_clean` filename from the detected image format, not the supplied MIME type or extension. - -Detailed wording boundaries and provenance are recorded in [Image Metadata privacy and verification](./docs/image-metadata-privacy.md). - - -## Images to PDF - -Images to PDF is available at `/tools/pdf/images-to-pdf/`. - -- `app.js` manages picker/drop input, duplicate-preserving queue state, ordering, removal, settings, progress, and save behavior. -- `tools/shared/image.js` validates and decodes JPEG, PNG, and WebP using browser-local APIs shared with Image Converter. -- `pdf.js` owns page geometry, image placement, sequential preparation, and jsPDF generation. -- Preview object URLs and temporary download URLs are revoked when no longer needed. -- File admission validates JPEG, PNG, and WebP signatures before browser decoding; a supported signature may override a misleading MIME type or extension. -- Individual files are limited to 50 MiB, queues to 100 files and 500 MiB, image dimensions to 16,384 pixels per side, and decoded images to 50,000,000 pixels. -- Mixed batches keep valid files and report each rejected filename with a localized reason. - -Images are decoded and converted sequentially so the tool does not keep every full decoded image in memory at once. +- Process supported file contents locally with browser APIs and same-origin libraries. +- Make bounded, tool-specific privacy claims instead of promising complete anonymity or sanitization. +- Keep production processing free of file uploads, analytics, telemetry, remote codecs, and runtime CDNs. +- Vendor audited runtime dependencies on the Secure Tools origin where practical. +- Preserve clear resource limits, failure handling, keyboard access, responsive layouts, and six-language support. +- Keep source and Network-panel behavior inspectable. -## PDF Merge +See the [privacy model](./docs/privacy-model.md) for exact guarantees and boundaries. -PDF Merge is available at `/tools/pdf/merge/`. - -- PDF MIME type is accepted directly; `.pdf` is used only as a fallback when the browser supplies no MIME type. -- Files are checked locally and the queue displays filename, size, and page count. -- Duplicate files are allowed and remain in the chosen order. -- Pages are copied with `pdf-lib`, preserving their PDF page content, dimensions, and orientation instead of rasterizing them. -- Source files are read in queue order during generation rather than retaining duplicate `ArrayBuffer` copies. -- Single-file, multi-file, multi-page, mixed-size, and repeated merges use the same path. -- Malformed, unsupported, encrypted, and password-protected files receive clear errors. Password entry and decryption are intentionally not implemented. -- The File System Access save picker is used when available; other browsers receive a local Blob download. - -Shared filename, file-size, ordering, save-picker, and download behavior lives in `tools/shared/`. - -## PDF Split - -PDF Split is available at `/tools/pdf/split/` and accepts one source PDF at a time. - -- Extract mode accepts individual pages and ascending ranges, preserves the explicit order, and intentionally preserves duplicate page references. -- Every-page mode creates one PDF per source page. -- Fixed-interval mode creates sequential groups and includes any remainder in the final file. -- `pdf-lib` copies original PDF pages without rasterizing them, preserving page dimensions and selectable/vector content. -- Multi-file modes generate outputs sequentially and add each `Uint8Array` to one local JSZip archive. They do not use base64 or trigger uncontrolled individual downloads. -- Output names use the shared sanitizer and sortable zero-padded page numbers. -- The source is read once during generation. Output documents are created one group at a time; the finished archive necessarily retains its entries until the ZIP Blob is produced. -- Unsupported, malformed, encrypted, and password-protected documents fail without attempting to bypass protection. -- English/Korean copy, shared theme controls, keyboard-labelled controls, live status, honest progress phases, and reduced-motion foundations are reused from the site architecture. - -A single extracted PDF uses the existing save-picker/download fallback. Multi-output modes save one predictable ZIP archive. - -## PDF to Images - -PDF to Images is available at `/tools/pdf/to-images/` for one local PDF at a time. - -- All-pages mode follows source order. Selected-pages mode reuses the PDF Split parser, preserving explicit order and duplicate references. -- PDF.js `6.2.108` and its worker are reused through `tools/shared/pdf-renderer.js`; both runtime files remain same-origin with network-fetched assets, WASM, and evaluation disabled. -- PNG uses lossless canvas encoding. JPEG and WebP expose quality from `0.5` to `1.0`, defaulting to `0.92`; unsupported WebP encoding fails with a localized error. -- Output scale is limited to `1×`, `1.5×`, `2×`, or `3×`. Every rendered page is capped at 16,384 pixels per dimension and 50,000,000 pixels total. -- At most two pages render concurrently. Each page canvas is encoded with `canvas.toBlob()`, reset to `1×1`, and its PDF.js page resources are cleaned before the queue advances. -- One selected page saves directly. Multiple images are converted to `Uint8Array` entries and added in selection order to one JSZip `3.10.1` archive without base64 conversion or multiple downloads. -- Names use the shared sanitizer and source page numbers, such as `report_page_005.png`. Repeated source pages receive deterministic suffixes such as `report_page_005_2.png` so ZIP entries are not overwritten. -- An `AbortController` cancels active rendering. Replacing the source first stops the current job, while a separate loading state prevents overlapping PDF inspection reads. - -The File System Access save picker is used when available, with the shared Blob-download fallback elsewhere. The source PDF remains unchanged. - - -## PDF Organizer -PDF Organizer is available at `/tools/pdf/organize/` for one local source PDF at a time. - -- An explicit page model tracks original page identity, current order, absolute rotation, and removal state independently of the DOM. -- PDF.js renders bounded 200 CSS-pixel thumbnails with at most two concurrent render tasks. Its same-origin module and worker run with optional network-fetched assets and WASM disabled. -- Pointer dragging and semantic move-earlier/move-later buttons provide equivalent ordering paths. -- Rotation uses normalized 0/90/180/270-degree state. Reset recreates the original order, rotations, and page set without rereading the source. -- Export uses `pdf-lib.copyPages` and page rotation metadata; it never uses thumbnail canvases, so original vector content, selectable text, embedded images, and page dimensions remain intact. -- Replacing or clearing a source cancels render tasks, destroys the PDF.js document/worker, clears thumbnail canvases, and releases retained source references. - -The original source file is never modified. The File System Access save picker is used when available, with the shared Blob-download fallback elsewhere. - -## PDF Metadata Inspector & Cleaner - -PDF Metadata Inspector & Cleaner is available at `/tools/pdf/metadata/` for one local PDF at a time. - -- The explicit metadata model inspects Title, Author, Subject, Keywords, Creator, Producer, Creation Date, and Modification Date from the standard PDF document-info dictionary. -- Values remain raw in application state while the UI formats dates with `Intl.DateTimeFormat`, safely replaces surfaced null characters for display, and limits individual rendered values to 2,000 characters. Cleaning still targets the complete underlying field. -- Shows a compact source card and decoded values first, with all eight supported document-info fields available in a native details disclosure. -- Privacy Clean removes every present supported document-info field. Customize exposes only the same eight class-level field controls; missing fields remain disabled and individual value editing is not offered. -- Cleaning edits the loaded PDF with `pdf-lib` using `updateMetadata: false`; pages are not rasterized, copied from screenshots, or reconstructed. -- After serialization, the tool reloads the produced bytes and inspects all supported fields again. Every requested field must be absent, and page count, dimensions, and rotation must match before any output is written; a retained requested field fails closed. -- Repeated cleaning continues from the previously verified output bytes. Loading or clearing a source releases the prior model, comparison, and retained byte references. -- The original PDF is never modified. Saving uses the shared File System Access picker where available and the revoking Blob-download fallback elsewhere. - -The supported scope is deliberately narrow: this tool removes supported PDF document-info metadata, not every possible forensic artifact or embedded information source. `pdf-lib` 1.17.1 does not expose a reliable public API for complete XMP inspection/removal, so Sprint 8 does not use fragile binary manipulation and does not claim to remove XMP packets, attachments, annotations, hidden content, or other embedded structures. Broader structural sanitization is deferred to future hardening work. - -## Local processing dependencies - -All processing libraries are pinned and served as same-origin static files. Production pages do not load a CDN. - -### jsPDF - -- Version: `4.2.1` -- Purpose: Images to PDF generation -- Package: `jspdf@4.2.1` from npm -- License: MIT -- Details: [assets/vendor/jspdf/README.md](./assets/vendor/jspdf/README.md) +## Available tools -### pdf-lib +### PDF -- Version: `1.17.1` -- Purpose: PDF inspection, document-info cleaning, page copying, and merge output -- Package: `pdf-lib@1.17.1` from npm -- License: MIT -- Details and hashes: [assets/vendor/pdf-lib/README.md](./assets/vendor/pdf-lib/README.md) +- [Images to PDF](./tools/pdf/images-to-pdf/) — arrange JPEG, PNG, and WebP images and save one PDF. +- [PDF Merge](./tools/pdf/merge/) — combine validated PDFs without rasterizing pages. +- [PDF Split](./tools/pdf/split/) — extract ranges or produce per-page and fixed-interval archives. +- [PDF Organizer](./tools/pdf/organize/) — preview, reorder, rotate, remove, and export pages. +- [PDF to Images](./tools/pdf/to-images/) — render pages to PNG, JPEG, or WebP. +- [PDF Metadata Inspector & Cleaner](./tools/pdf/metadata/) — inspect and remove supported document-info fields. -### JSZip +### Image -- Version: `3.10.1` -- Purpose: local multi-file Image Converter, PDF Split, and PDF to Images archives -- Package: `jszip@3.10.1` from npm -- License choice: MIT -- Details and hashes: [assets/vendor/jszip/README.md](./assets/vendor/jszip/README.md) +- [Image Converter](./tools/image/converter/) — convert JPEG, PNG, and WebP batches. +- [Image Resize](./tools/image/resize/) — resize batches by pixels or percentage. +- [Image Compressor](./tools/image/compress/) — quality-compress images and compare byte results. +- [Image Metadata Inspector & Cleaner](./tools/image/metadata/) — inspect supported metadata and save a verified cleaned copy without pixel re-encoding. -### PDF.js +### Privacy -- Version: `6.2.108` -- Purpose: local PDF Organizer thumbnails and PDF to Images page rendering -- Package: `pdfjs-dist@6.2.108` from npm -- License: Apache-2.0 -- Main module and worker: same-origin files under `assets/vendor/pdfjs/` -- Details and hashes: [assets/vendor/pdfjs/README.md](./assets/vendor/pdfjs/README.md) +The [Privacy hub](./tools/privacy/) links to the specialized Image and PDF metadata tools. It is a cross-category navigation surface, not a generic sanitizer. Scan/OCR and Media remain planned. -### secure-metadata +Detailed formats, limits, and behavior are listed in [tool status](./docs/tool-status.md). -- Version/tag: `v0.1.1` -- Release commit: `cdcd138e48d30618b6d76f7c6538cd43ad660b53` -- Purpose: local JPEG, PNG, and WebP metadata inspection, Privacy Clean, and fail-closed verification -- Browser artifact SHA-256: `4bfcc9e0e484db12192e46f076c19cf69cd36c496c7cfbb5a71c1057cbcccba1` -- License: MIT -- Runtime dependencies: 0 -- Integration: manually pinned same-origin GitHub Release artifact; not an npm runtime dependency -- Details and provenance: [assets/vendor/secure-metadata/README.md](./assets/vendor/secure-metadata/README.md) +## Interface -Each dependency keeps its license and package metadata beside the vendored browser build. +Secure Tools includes English, Korean, Japanese, Spanish, German, and French interface catalogs. Theme choices are Light, Dark, and System. Language and theme preferences are the only application values stored in `localStorage`. ## Local development @@ -350,78 +51,29 @@ Serve the repository over HTTP so ES Modules load correctly: python -m http.server 8000 ``` -Then open [http://localhost:8000](http://localhost:8000). Do not use a `file://` URL. +Open [http://localhost:8000](http://localhost:8000). Do not use a `file://` URL. -Run the complete local and CI validation entry point with: +Run the complete validation suite with: ```bash node tests/run-all.mjs ``` -It checks JavaScript syntax and runs Image Converter, Image Resize, Image Compressor, Image Metadata, Images to PDF, PDF Merge, PDF Split, PDF Organizer, PDF to Images, PDF Metadata, category-first homepage, system typography, CJK wrapping, long-copy layout, six-language catalog parity and placeholders, locale detection and persistence, static resource, privacy/network, security-hardening, dependency-integrity, save-path, ZIP, and CI workflow regression coverage. Test fixtures are generated deterministically; CI never processes real user files. - -## Production security controls - -Secure Tools remains a static, local-processing application. Production pages enforce a meta-delivered Content Security Policy with `default-src 'self'`, `script-src 'self'`, `style-src 'self'`, `img-src 'self' blob: data:`, `connect-src 'none'`, `object-src 'none'`, `frame-src 'none'`, `base-uri 'self'`, and `form-action 'self'`. No `unsafe-inline` or `unsafe-eval` exception is used. - - -The early theme bootstrap and GitHub Pages 404 base-path bootstrap are same-origin files under `js/`; production HTML contains no inline script or style blocks. Blob and data image sources are allowed only for local image previews and image/PDF preparation. Normal user navigation to GitHub links is not a network API connection and remains available. - -Images to PDF uses layered validation: - -1. pre-decode file and queue resource limits; -2. JPEG, PNG, or WebP magic-byte recognition from a 12-byte local slice; -3. browser decoding; and -4. post-decode dimension and pixel-count checks before canvas conversion. - -The obsolete `image2pdf_proto.html` prototype was removed from the deployed tree; Git history preserves it. `tests/security-hardening.test.mjs` verifies the pinned dependency, limits and boundaries, signatures and spoofing cases, safe filename DOM sinks, CSP coverage, inline-code absence, prototype removal, and absence of first-party runtime network APIs. - - -## Continuous integration - -`.github/workflows/ci.yml` runs on every Pull Request and every push to `main`. The single validation job uses Node.js 24 to: - -- check the changed commit range for whitespace errors; -- syntax-check first-party JavaScript and test modules; and -- run `node tests/run-all.mjs`. - -CI adds no deployment, telemetry, package installation, or backend. Production remains a static site. - -## Development workflow - -Secure Tools uses lightweight trunk-based development: - -1. Update clean local `main` with `git pull --ff-only origin main`. -2. Create a short-lived `feature/`, `fix/`, `refactor/`, or `docs/` branch. -3. Commit logical stages with the Secure Tools emoji-tag convention. -4. Run tests, `git diff --check`, route/resource checks, and applicable privacy/accessibility QA. -5. Push the short-lived branch, open a pull request, and use a normal merge commit after checks pass. -6. Sync `main`, verify it matches `origin/main`, and delete the completed local and remote branch. - -Do not force-push or rewrite shared `main` history. - -## GitHub Pages deployment - -1. Push the integrated `main` branch to GitHub. -2. Open **Settings → Pages** in the repository. -3. Under **Build and deployment**, choose **Deploy from a branch**. -4. Select `main` and the repository root (`/`). -5. Save and wait for GitHub Pages to publish the static files. - -Relative links keep the site compatible with the `/Secure_Tools/` project subpath, local development, and a root-hosted custom domain. The checked-in `404.html` supports GitHub Pages fallback behavior. +## Documentation -## Network dependencies +The [documentation index](./docs/README.md) links to the maintained sources of truth for: -Production routes load only same-origin HTML, CSS, JavaScript, and vendored libraries. They make no analytics, font, file-upload, embed, or API requests. GitHub is contacted only after a user follows a source link. +- architecture and delivery; +- privacy, local processing, and network boundaries; +- production dependencies and vendoring; +- production and planned tool status; +- release QA evidence; +- UX, accessibility, localization, and format-specific privacy audits. -The historical prototype is absent from the deployed tree. External URLs in documentation, licenses, and source links are informational or user-initiated; no production processing dependency is fetched remotely. -## Deferred work +Release history is recorded in the [changelog](./CHANGELOG.md). The current v2.0.0 line remains in pre-release observation. -- Broader PDF modification, compression, and encryption workflows -- Broader XMP and structural PDF metadata sanitization -- Scan/OCR and media tools -- Offline/PWA support +## Repository and license -## License +Source: [SecureToolsProject/Secure_Tools](https://github.com/SecureToolsProject/Secure_Tools) -See [LICENSE](./LICENSE). Vendored third-party code retains its own license alongside each dependency. +See [LICENSE](./LICENSE). Vendored third-party code retains its own license beside each dependency. diff --git a/README.original.md b/README.original.md deleted file mode 100644 index cd34d8d..0000000 --- a/README.original.md +++ /dev/null @@ -1 +0,0 @@ -# Secure_Tools \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..521d02a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,23 @@ +# Secure Tools documentation + +The root [README](../README.md) introduces Secure Tools. This directory owns detailed design, operational, privacy, and audit information. + +## Current documentation + +| Document | Responsibility | +| --- | --- | +| [Architecture](./architecture.md) | Static application structure, shared browser foundations, delivery, and future ecosystem direction | +| [Privacy model](./privacy-model.md) | Local-processing and network boundaries, storage, security controls, and bounded privacy claims | +| [Dependencies](./dependencies.md) | Production runtime inventory, versions, vendoring, licenses, and integrity ownership | +| [Tool status](./tool-status.md) | Production and planned surfaces, supported formats, behavior, and resource boundaries | +| [Image Metadata privacy](./image-metadata-privacy.md) | Format-specific inspection, cleaning, preservation, and verification semantics | +| [UX consistency audit](./ux-consistency-audit.md) | Shared interaction, accessibility, responsive, theme, and historical browser-QA findings | +| [i18n copy review](./i18n-copy-review.md) | Localization coverage and editorial review record | + +## Release evidence + +- [v1.0.0 release QA](./release-qa.md) is a historical Sprint 11 release-candidate snapshot. Its unchecked items remain historical and are not current requirements. +- [v2 promotion QA](./v2-release-qa.md) preserves the automated, manual Chrome, Orientation-regression, and promotion evidence for the v2.0.0 pre-release line. +- The root [changelog](../CHANGELOG.md) records release and change history; it is not a technical specification. + +Detailed artifact hashes and upstream provenance remain beside each dependency under [`assets/vendor/`](../assets/vendor/), where automated release gates verify them. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..7e6a6bc --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,72 @@ +# Architecture + +## Application model + +Secure Tools is a static GitHub Pages application built with semantic HTML, CSS, and Vanilla JavaScript ES Modules. It has no framework, build step, backend, database, authentication service, runtime API, or required package installation. + +Production routes load application code and pinned libraries from the same origin. File-processing workflows run through browser APIs and in-memory data. The [privacy model](./privacy-model.md) defines the limits of that statement. + +## Information architecture + +The homepage points to stable category hubs instead of maintaining a flat list of every utility: + +- PDF: six production tools; +- Image: four production tools; +- Privacy: a cross-category hub for the two metadata tools; +- Scan/OCR and Media: planned, non-interactive surfaces. + +Each production tool owns a route under `tools///`. The legacy `/tools/image-to-pdf/` route is a static migration page to `/tools/pdf/images-to-pdf/` with a visible fallback link. + +```text +. +├── index.html, 404.html +├── about/, privacy/ +├── css/ shared design and page styles +├── js/ theme, i18n, configuration, locale catalogs +├── tools/ +│ ├── shared/ input, validation, output, save, PDF, and UI foundations +│ ├── pdf/ PDF hub and production tools +│ ├── image/ Image hub and production tools +│ ├── privacy/ metadata-tool navigation hub +│ ├── scan/, media/ planned category pages +│ └── image-to-pdf/ legacy static redirect +├── assets/vendor/ pinned same-origin runtime libraries +├── docs/ technical, privacy, and audit records +└── tests/ static and functional validation +``` + +The current production inventory and tool-specific behavior live in [tool status](./tool-status.md). + +## Shared browser foundations + +- `js/main.js` initializes shared theme and internationalization behavior. +- `js/theme.js` owns Light, Dark, and System selection, OS preference observation, and persistence. +- `js/i18n.js` resolves six supported languages, applies translations without reload, updates document metadata and ``, and preserves tool state when language changes. +- `js/config.js` centralizes repository links. +- `tools/shared/` owns common file admission, signature validation, image/PDF helpers, queue conventions, local save behavior, and shared tool presentation. +- The File System Access API is used when available; a revoking Blob-download fallback serves other browsers. + +Tool implementations retain specialized models when their workflows differ. Organizer uses a page grid and PDF rendering lifecycle; Metadata tools use bounded inspection models and fail-closed output verification. Shared UI does not erase these tool-specific guarantees. + +## Dependencies and processing + +Runtime libraries are checked into `assets/vendor/` with their package metadata, license, upstream provenance, and integrity information. Production does not install packages or fetch CDN code. See [dependencies](./dependencies.md). + +Image conversion, resizing, and compression use browser decode, Canvas, and encode APIs. PDF manipulation uses pinned PDF libraries; PDF rendering uses a same-origin PDF.js module and worker with optional remote assets disabled. Metadata cleaning uses format-specific paths documented in [tool status](./tool-status.md) and [Image Metadata privacy](./image-metadata-privacy.md). + +## Development and delivery + +Local development requires only an HTTP server. The authoritative test entry point is `node tests/run-all.mjs`. + +`.github/workflows/ci.yml` validates pull requests and pushes to `main` using Node.js 24. It checks commit-range whitespace, JavaScript syntax, and the repository test suite without installing a production dependency or adding deployment behavior. + +Development uses short-lived branches and normal merge commits. Shared `main` history is not force-pushed or rewritten. GitHub Pages can publish `main` from the repository root; relative links support both the `/Secure_Tools/` project path and root-hosted deployments. + +## Ecosystem direction + +Secure Tools may evolve as both: + +- a host for lightweight built-in browser tools; and +- a discovery hub for separately deployed companion applications that need different runtime or resource models. + +This is a direction, not a current integration contract. There is no companion registry, external-application schema, plugin framework, service discovery mechanism, or v3 navigation implementation in the present architecture. diff --git a/docs/dependencies.md b/docs/dependencies.md new file mode 100644 index 0000000..3e93481 --- /dev/null +++ b/docs/dependencies.md @@ -0,0 +1,25 @@ +# Production dependencies + +Secure Tools pins production libraries as same-origin static files under `assets/vendor/`. Runtime pages do not install packages, use a CDN, or automatically check for updates. + +| Dependency | Version | Purpose | License | Detailed record | +| --- | ---: | --- | --- | --- | +| jsPDF | 4.2.1 | Images to PDF generation | MIT | [Vendor README](../assets/vendor/jspdf/README.md) | +| pdf-lib | 1.17.1 | PDF inspection, document-info cleaning, page copying, merge, split, and organization | MIT | [Vendor README](../assets/vendor/pdf-lib/README.md) | +| JSZip | 3.10.1 | Local multi-file Image and PDF archives | MIT license choice | [Vendor README](../assets/vendor/jszip/README.md) | +| PDF.js (`pdfjs-dist`) | 6.2.108 | PDF Organizer thumbnails and PDF to Images rendering | Apache-2.0 | [Vendor README](../assets/vendor/pdfjs/README.md) | +| secure-metadata | 0.1.1 | JPEG, PNG, and WebP metadata inspection, cleaning, and verification | MIT | [Vendor README](../assets/vendor/secure-metadata/README.md) | + +## Vendoring and integrity + +Each vendor directory contains the deployed runtime files plus its license and package/provenance metadata. The vendor README is the human-readable source of truth for upstream artifacts and exact runtime hashes. `tests/release-gate.test.mjs` verifies the approved file inventory, versions, metadata, licenses, and runtime SHA-256 values. + +The summary table intentionally does not duplicate every artifact hash. Keeping exact values beside the bytes they validate reduces drift while preserving a navigable inventory here. + +## secure-metadata integration + +The current runtime is `secure-metadata v0.1.1`, release commit `cdcd138e48d30618b6d76f7c6538cd43ad660b53`. Its browser artifact is `secure-metadata-0.1.1.browser.js` with SHA-256 `4bfcc9e0e484db12192e46f076c19cf69cd36c496c7cfbb5a71c1057cbcccba1`. + +The browser and package artifacts were verified against the published `SHA256SUMS` manifest and GitHub asset digests. The deployed browser bytes match the build inside the release package. Secure Tools imports that artifact only from its own origin; replacement requires a new explicit provenance and integrity review. + +The supported privacy and preservation behavior is documented separately in [Image Metadata privacy and verification](./image-metadata-privacy.md). diff --git a/docs/privacy-model.md b/docs/privacy-model.md new file mode 100644 index 0000000..74f10f0 --- /dev/null +++ b/docs/privacy-model.md @@ -0,0 +1,42 @@ +# Privacy and local-processing model + +## What local processing means + +For supported production workflows, Secure Tools reads and transforms file contents in the browser on the user's device. It does not send those contents to an application upload service. The site requires no account and includes no analytics, advertising, behavioral telemetry, or tracking pixels. + +This guarantee applies to documented production tools and supported formats. It is not a claim that every browser extension, operating system component, external destination, unsupported file structure, or future companion application has the same behavior. + +## Network boundary + +Production pages load HTML, CSS, JavaScript, and vendored libraries from the Secure Tools origin. First-party processing code does not use `fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`, or `sendBeacon` for file processing. It does not load runtime codecs, workers, fonts, translations, or libraries from a CDN. + +Production Content Security Policy uses `connect-src 'none'` and restricts scripts, styles, frames, objects, base URLs, and form actions to the documented static model. User navigation to an external source link is a deliberate browser navigation governed by the destination's policy, not a processing request. + +Blob URLs and data URLs are browser-local references used for previews, prepared images, and downloads. The application revokes temporary object URLs when they are no longer needed. + +## Storage and source handling + +Theme and language preferences are the only application values stored in `localStorage`. Source files and outputs are not placed in application cloud storage. Tools retain in-memory source state only as needed for the active workflow and release object URLs, rendering tasks, models, or byte references when sources are cleared or replaced. + +Save operations use the browser's File System Access picker where available and a local Blob-download fallback elsewhere. Cancellation and write failures do not silently convert into successful saves. + +## Input and resource boundaries + +Tools validate supported signatures and apply bounded file, queue, dimension, pixel, page, render, metadata-display, and aggregate-work limits appropriate to each workflow. These controls reduce accidental memory and workload pressure; they are not malware scanning or a guarantee that arbitrary hostile files are safe. + +The exact production surface and shared image limits are recorded in [tool status](./tool-status.md). Automated tests cover spoofed signatures, corrupt and protected inputs where applicable, runtime network invariants, dependency integrity, safe DOM sinks, save paths, and resource boundaries. + +## Bounded privacy claims + +Secure Tools does not claim that a file is “100% private,” completely anonymous, universally sanitized, or free of all hidden information. + +- Canvas-based Image Converter, Resize, and Compressor create new pixel encodings and do not preserve EXIF metadata, but they are not configurable forensic metadata cleaners. +- Image Metadata reports only structures supported by the pinned parser. Partial or opaque results remain explicitly non-exhaustive; unknown structures are not guessed away. +- PDF Metadata removes and verifies the eight supported document-info fields. It does not claim complete XMP, attachment, annotation, hidden-content, or structural sanitization. +- Images to PDF and PDF page-copying tools preserve or transform content according to their documented workflow; they are not privacy cleaners. + +Format-specific Image Metadata semantics—including decoded versus opaque data, EXIF Orientation and ICC preservation, unknown structures, and fail-closed verification—live in [Image Metadata privacy and verification](./image-metadata-privacy.md). + +## Verification + +Privacy behavior is inspectable through source code, Content Security Policy, the browser Network panel, vendored dependency records, and automated tests. Release-specific automated and manual results are retained in the [documentation index](./README.md#release-evidence). diff --git a/docs/tool-status.md b/docs/tool-status.md new file mode 100644 index 0000000..6968602 --- /dev/null +++ b/docs/tool-status.md @@ -0,0 +1,81 @@ +# Tool status and scope + +## Current surface + +| Category | Tool or surface | Status | Formats / scope | +| --- | --- | --- | --- | +| PDF | [Images to PDF](../tools/pdf/images-to-pdf/) | Production | JPEG, PNG, WebP → PDF | +| PDF | [PDF Merge](../tools/pdf/merge/) | Production | Ordered PDF page copying | +| PDF | [PDF Split](../tools/pdf/split/) | Production | Ranges, every page, fixed intervals | +| PDF | [PDF Organizer](../tools/pdf/organize/) | Production | Preview, reorder, rotate, remove, export | +| PDF | [PDF to Images](../tools/pdf/to-images/) | Production | PDF pages → PNG, JPEG, WebP | +| PDF | [PDF Metadata Inspector & Cleaner](../tools/pdf/metadata/) | Production | Eight supported document-info fields | +| Image | [Image Converter](../tools/image/converter/) | Production | JPEG, PNG, WebP conversion | +| Image | [Image Resize](../tools/image/resize/) | Production | Pixel or percentage batch resize | +| Image | [Image Compressor](../tools/image/compress/) | Production | JPEG/WebP quality and PNG re-encoding | +| Image | [Image Metadata Inspector & Cleaner](../tools/image/metadata/) | Production | Supported JPEG, PNG, WebP metadata | +| Privacy | [Privacy hub](../tools/privacy/) | Production hub | Navigation to Image and PDF metadata tools | +| Scan/OCR | Category surface | Planned | No production processing tool | +| Media | Category surface | Planned | No production processing tool | + +“Production” means linked and covered by the current repository validation. “Planned” cards are non-interactive. Secure Tools may later link separately deployed companion applications, but no Companion status or integration exists on the live site today. + +## Shared Image boundaries + +Image admission validates signatures before decoding. Image Converter, Resize, Compressor, and Images to PDF share a 50 MiB per-file limit, 100-file queue limit, 500 MiB aggregate queue limit, 16,384-pixel per-dimension limit, and 50-megapixel per-image decoded limit. Converter, Resize, and Compressor also enforce a 200-megapixel aggregate work limit appropriate to their output path. + +Queues remain available after recoverable validation, decode, encode, archive, save, or cancellation failures. Unicode output bases are limited to 120 characters and 180 UTF-8 bytes, with deterministic collision suffixes. Multi-output workflows use the same-origin JSZip runtime and predictable ZIP names. + +## Image tools + +### Image Converter + +Converts signature-validated JPEG, PNG, and WebP batches sequentially through browser decode, Canvas, and encode APIs. Explicit browser orientation handling renders normally displayed camera images in their intended orientation. JPEG and WebP expose lossy quality; PNG does not. PNG/WebP preserve alpha while JPEG flattens transparency onto white. Canvas re-encoding strips EXIF and other embedded image metadata but is not presented as configurable metadata cleaning. One output saves directly; multiple outputs use `converted_images.zip`. + +### Image Resize + +Supports pixel bounding dimensions and percentage scaling, preserves aspect ratio by default, permits an automatic dimension, and disables enlargement by default. Original/JPEG/PNG/WebP output follows the same transparency and quality rules as Converter. Outputs use `_resized` names; batches use `resized_images.zip`. A 200-megapixel aggregate output-work limit applies. + +### Image Compressor + +Preserves oriented pixel dimensions while re-encoding in Original/JPEG/PNG/WebP format. JPEG and WebP use an explicit quality setting; PNG is re-encoded without a misleading lossy-quality control. Results report original size, output size, signed byte difference, and percentage change, including increases. Outputs use `_compressed` names and `compressed_images.zip`. The tool does not resize, crop, target a byte size, or edit metadata selectively. + +### Image Metadata Inspector & Cleaner + +Accepts one JPEG, PNG, or WebP file and uses the pinned `secure-metadata v0.1.1` browser artifact without decoding or re-encoding pixels. It separates decoded fields from opaque detected containers and presents partial inspection as non-exhaustive. Privacy Clean and Customize operate only on supported metadata classes; verification must pass before output is saved. Valid unambiguous JPEG EXIF Orientation and ICC color information are preserved according to policy. Full guarantees and exclusions are in [Image Metadata privacy and verification](./image-metadata-privacy.md). + +## PDF tools + +### Images to PDF + +Maintains a duplicate-preserving ordered image queue, validates image signatures, prepares sources sequentially, and uses jsPDF for page geometry and output. Preview and download object URLs are revoked. Mixed batches retain valid files and report rejected sources. + +### PDF Merge + +Accepts the PDF MIME type directly and uses `.pdf` only when the browser supplies no MIME type. It validates local PDFs, permits duplicates, and copies pages in queue order with pdf-lib instead of rasterizing them. Malformed, unsupported, encrypted, and password-protected inputs fail clearly; password entry and decryption are not implemented. Source files are read in generation order rather than retained as duplicate buffers. + +### PDF Split + +Extract mode preserves explicit page order and duplicate references. Every-page and fixed-interval modes generate sequential outputs, including a final remainder group. Pages are copied without rasterization. Output names use the shared sanitizer and sortable zero-padded page numbers. One output saves directly; multiple outputs are collected into one local ZIP. + +### PDF Organizer + +PDF.js renders bounded 200 CSS-pixel thumbnails with at most two concurrent tasks. Users can reorder, rotate, and remove pages; export uses `pdf-lib.copyPages` and page rotation metadata rather than thumbnail canvases, preserving original page content and dimensions. Clearing or replacing a source cancels render tasks and releases the document, worker, canvases, and retained references. + +### PDF to Images + +All-pages and selected-pages modes render through same-origin PDF.js. Selection preserves explicit order and duplicates. PNG is lossless; JPEG/WebP expose bounded quality. Scale is limited to 1×, 1.5×, 2×, or 3×, with 16,384-pixel and 50-megapixel page limits and at most two concurrent renders. One page saves directly; multiple pages use a ZIP archive. + +### PDF Metadata Inspector & Cleaner + +Inspects Title, Author, Subject, Keywords, Creator, Producer, Creation Date, and Modification Date from the standard document-info dictionary. Values remain raw in application state while the UI localizes dates, safely surfaces null characters, and limits each displayed value to 2,000 characters. Privacy Clean removes all present supported fields; Customize targets the same class-level fields. The output is reloaded and checked for requested removal plus page-count, dimension, and rotation preservation before save. This does not claim complete XMP, attachment, annotation, hidden-content, or structural sanitization. + +## Deferred directions + +Broader PDF modification, compression, encryption, XMP/structural sanitization, Scan/OCR, Media, and offline/PWA work remain deferred. Separately deployed companion applications are an architectural possibility, not a current product status or integration. + +## Related guarantees + +- [Privacy model](./privacy-model.md) defines local processing, network behavior, storage, and bounded claims. +- [Dependencies](./dependencies.md) records the pinned production runtime inventory. +- [v2 promotion QA](./v2-release-qa.md) preserves automated and manual evidence for this production surface. diff --git a/docs/v2-release-qa.md b/docs/v2-release-qa.md index 2aff03d..267cf43 100644 --- a/docs/v2-release-qa.md +++ b/docs/v2-release-qa.md @@ -1,19 +1,20 @@ # v2 Promotion QA -This is the live promotion gate for the Secure Tools `v2` integration branch. It separates reproducible automated evidence from interactive browser evidence. `BLOCKED` and `NOT RUN` never mean `PASS`. +This is the preserved promotion record for the Secure Tools v2.0.0 pre-release line. It separates reproducible automated evidence from interactive browser evidence. `BLOCKED` and `NOT RUN` never mean `PASS`. ## Decision -**READY FOR PROMOTION** as of 2026-08-27. This means `v2` is ready for a separate promotion decision; it has not been merged to `main`, tagged, released, or deployed. +**PROMOTED** on 2026-08-27 after the recorded gate reached **READY FOR PROMOTION**. PR #60 merged the approved `v2` tree to `main` as commit `1d1d4a6bf055eb98f6902139c2dd4de1339b8840`; `v2.0.0-rc.1` was subsequently published as a pre-release. - Automated local gate: **PASS** — `git diff --check` and `node tests/run-all.mjs` completed successfully on Windows with Node.js 24. - Static privacy, network, CSP, resource, dependency, route, localization, save-path, responsive-contract, and accessibility checks: **PASS**. - Automated / in-environment browser QA: **BLOCKED** before navigation by the local Chrome-control runtime failures documented below. - Manual local Chrome QA: **PASS** — the user completed the release-required interactive checks in Chrome 151.0.7922.174 (Official Build, 64-bit). - Metadata Orientation regression: **RESOLVED / PASS** — the user manually verified the corrected Orientation=6 JPEG behavior after the secure-metadata v0.1.1 integration. -- Promotion to `main`, release tagging, release publication, and deployment: **NOT RUN** and outside this documentation-only scope. +- Promotion to `main`: **PASS** — PR #60 used a normal merge commit and preserved the validated v2 history. +- Pre-release publication: **PUBLISHED** — `v2.0.0-rc.1`; no stable v2.0.0 release is claimed by this record. -No unresolved release blocker remains in this gate. The branch-protection and Dependabot visibility observations below remain repository-hardening concerns, but the existing release policy does not define them as promotion blockers. Any new failed automated or CI check, privacy regression, unexplained runtime request, corrupt output, inaccessible primary path, or failed save would reopen the gate. +No unresolved release blocker remained at promotion. The branch-protection and Dependabot visibility observations below remain historical repository-hardening concerns; the existing release policy did not define them as promotion blockers. This document is version-specific evidence, not the active gate for future development. ## Sprint 17 audit disposition @@ -72,6 +73,7 @@ Audited on 2026-08-27 against repository records, immutable GitHub Release asset | secure-metadata | 0.1.1 immutable GitHub release artifact | Not an npm runtime dependency | PASS | - The v1.0.0 GitHub release is published; v1.0.0-rc.1 remains marked as a prerelease. +- The v2.0.0-rc.1 GitHub pre-release was published after the promotion evidence in this document passed; no stable v2.0.0 publication is claimed here. - `main` and `v2` returned “Branch not protected” from the GitHub branch-protection API. This is a repository-governance risk, not a change authorized by Sprint 17. - GitHub returned `403 Dependabot alerts are disabled for this repository`; vulnerability-alert visibility is therefore **NOT AVAILABLE**, not `PASS`. - secure-metadata alone was upgraded from 0.1.0 to the verified 0.1.1 browser Release artifact. No framework, package manager, build system, runtime dependency, CDN, or remote processing resource was added.