Compare commits

..
4 Commits
21 changed files with 1238 additions and 147 deletions
+2 -2
View File
@@ -5,5 +5,5 @@ TRAEFIK_NETWORK=internal
TRAEFIK_CERT_RESOLVER=netcup
# Keep these two values paired when deploying a newer published toolbox release.
TOOLBOX_RELEASE_VERSION=0.16.0
TOOLBOX_RELEASE_SHA256=2ae120dd54196428893420a236b32ee260a08af3e0d390362da3457d85110f4e
TOOLBOX_RELEASE_VERSION=0.19.0
TOOLBOX_RELEASE_SHA256=b6003d8b3eee8a13032527b014a381d832ba46108c35d0aee9e1cfa6a1b281e2
+44 -2
View File
@@ -2,8 +2,8 @@ ARG NGINX_IMAGE=nginxinc/nginx-unprivileged:1.31.3-alpine@sha256:18d67281256ded3
FROM ${NGINX_IMAGE} AS release
ARG TOOLBOX_RELEASE_VERSION=0.16.0
ARG TOOLBOX_RELEASE_SHA256=2ae120dd54196428893420a236b32ee260a08af3e0d390362da3457d85110f4e
ARG TOOLBOX_RELEASE_VERSION=0.19.0
ARG TOOLBOX_RELEASE_SHA256=b6003d8b3eee8a13032527b014a381d832ba46108c35d0aee9e1cfa6a1b281e2
ARG TOOLBOX_RELEASE_BASE_URL=https://git.add-ideas.de/lotobo/toolbox-portal/releases/download
RUN set -eu; \
@@ -26,6 +26,48 @@ RUN set -eu; \
test -f /tmp/toolbox/apps/svg/toolbox-app.json; \
test -f /tmp/toolbox/apps/auth/toolbox-app.json; \
test -f /tmp/toolbox/apps/sudoku/toolbox-app.json; \
test -f /tmp/toolbox/apps/colour/toolbox-app.json; \
test -f /tmp/toolbox/apps/office/toolbox-app.json; \
test -f /tmp/toolbox/apps/image/toolbox-app.json; \
test -f /tmp/toolbox/apps/file/toolbox-app.json; \
test -f /tmp/toolbox/apps/epub/toolbox-app.json; \
test -f /tmp/toolbox/apps/archive/toolbox-app.json; \
test -f /tmp/toolbox/apps/privacy/toolbox-app.json; \
test -f /tmp/toolbox/apps/crypto/toolbox-app.json; \
test -f /tmp/toolbox/apps/barcode/toolbox-app.json; \
test -f /tmp/toolbox/apps/network/toolbox-app.json; \
test -f /tmp/toolbox/apps/geo/toolbox-app.json; \
test -f /tmp/toolbox/apps/helper/toolbox-app.json; \
test -f /tmp/toolbox/apps/rand/toolbox-app.json; \
test -f /tmp/toolbox/apps/data/toolbox-app.json; \
test -f /tmp/toolbox/apps/diff/toolbox-app.json; \
test -f /tmp/toolbox/apps/time/toolbox-app.json; \
test -f /tmp/toolbox/apps/text/toolbox-app.json; \
test -f /tmp/toolbox/apps/unicode/toolbox-app.json; \
test -f /tmp/toolbox/apps/flow/toolbox-app.json; \
test -f /tmp/toolbox/apps/subtitle/toolbox-app.json; \
test -f /tmp/toolbox/apps/midi/toolbox-app.json; \
test -f /tmp/toolbox/apps/3d/toolbox-app.json; \
test -f /tmp/toolbox/apps/query/toolbox-app.json; \
test -f /tmp/toolbox/apps/scan/toolbox-app.json; \
test -f /tmp/toolbox/apps/package/toolbox-app.json; \
test -f /tmp/toolbox/apps/label/toolbox-app.json; \
test -f /tmp/toolbox/apps/font/toolbox-app.json; \
test -f /tmp/toolbox/apps/fixture/toolbox-app.json; \
test -f /tmp/toolbox/apps/minimize/toolbox-app.json; \
test -f /tmp/toolbox/apps/format-lab/toolbox-app.json; \
test -f /tmp/toolbox/apps/repro/toolbox-app.json; \
test -f /tmp/toolbox/apps/schema/toolbox-app.json; \
test -f /tmp/toolbox/apps/log/toolbox-app.json; \
test -f /tmp/toolbox/apps/binary/toolbox-app.json; \
test -f /tmp/toolbox/apps/git/toolbox-app.json; \
test -f /tmp/toolbox/apps/api/toolbox-app.json; \
test -f /tmp/toolbox/apps/mail/toolbox-app.json; \
test -f /tmp/toolbox/apps/calendar/toolbox-app.json; \
test -f /tmp/toolbox/apps/contact/toolbox-app.json; \
test -f /tmp/toolbox/apps/diagram/toolbox-app.json; \
test -f /tmp/toolbox/apps/token/toolbox-app.json; \
test -f /tmp/toolbox/apps/device/toolbox-app.json; \
rm "/tmp/${archive}"
FROM ${NGINX_IMAGE}
+148 -87
View File
@@ -1,7 +1,7 @@
# add·ideas Toolbox Portal
`toolbox-portal` is the static launcher and release assembler for the add·ideas
browser toolbox. Version `0.2.18` reads one same-origin catalogue, shows each app
browser toolbox. Version `0.2.22` reads one same-origin catalogue, shows each app
as a compact launch tile, and keeps personal pins, drag-and-drop ordering,
visibility, and appearance in the current browser. Pinned tools have their own
section; search, category, and clickable tag filters stay close to the tool
@@ -37,7 +37,18 @@ the SDK and portal together.
Vite uses `base: './'`, so the built portal works at `/` or a nested static path.
The development catalogue at `public/toolbox.catalog.json` points to assembled
paths (`./apps/pdf/`, `./apps/xslt/`, `./apps/onenote/`, `./apps/av/`,
`./apps/regex/`, `./apps/svg/`, `./apps/auth/`, and `./apps/sudoku/`).
`./apps/regex/`, `./apps/svg/`, `./apps/auth/`, `./apps/sudoku/`,
`./apps/colour/`, `./apps/office/`, `./apps/image/`, `./apps/file/`,
`./apps/epub/`, `./apps/archive/`, `./apps/privacy/`, `./apps/crypto/`,
`./apps/barcode/`, `./apps/network/`, `./apps/geo/`, `./apps/helper/`,
`./apps/rand/`, `./apps/data/`, `./apps/diff/`, `./apps/time/`,
`./apps/text/`, `./apps/unicode/`, `./apps/flow/`, `./apps/subtitle/`,
`./apps/midi/`, `./apps/3d/`, `./apps/query/`, `./apps/scan/`,
`./apps/package/`, `./apps/label/`, `./apps/font/`, `./apps/fixture/`,
`./apps/minimize/`, `./apps/format-lab/`, `./apps/repro/`, `./apps/schema/`,
`./apps/log/`, `./apps/binary/`, `./apps/git/`, `./apps/api/`, `./apps/mail/`,
`./apps/calendar/`, `./apps/contact/`, `./apps/diagram/`, `./apps/token/`, and
`./apps/device/`).
Those manifests will correctly appear as unavailable until an assembled release
is being served.
@@ -69,7 +80,7 @@ privacy and executable-code warning. Light, dark, and system modes are supported
## Production deployment behind Traefik
The committed `compose.yaml` is the shortest production path. Its release
container downloads the immutable Toolbox 0.16.0 ZIP during the image build,
container downloads the immutable Toolbox 0.19.0 ZIP during the image build,
verifies SHA-256 before extracting it, and then copies only the verified static
files into the pinned unprivileged nginx image. Node.js and a local portal
assembly are not required on the deployment host.
@@ -133,10 +144,18 @@ The app release should also publish a matching `.sha256` sidecar. The manifest
must declare the pinned reverse-DNS id and version. Application and portal
versions are independent.
`release/toolbox.lock.json` is the reviewed v0.16.0 lock. Its URLs and checksums
pin the published PDF Tools 0.4.4, XSLT Tools 0.4.3, OneNote Tools 0.3.4,
`release/toolbox.lock.json` is the reviewed Toolbox v0.19.0 / Portal v0.2.22
lock. Its URLs and checksums pin the published PDF Tools 0.4.4, XSLT Tools
0.4.3, OneNote Tools 0.3.4,
Audio & Video Tools 0.3.0, Regex Tools 0.4.2, SVG Tools 0.1.0, OTP & Passkey
Tools 0.3.0, and Sudoku Tools 0.2.1 release bytes. Use
Tools 0.3.1, Sudoku Tools 0.2.1, Colour Tools 0.1.0, Office Tools 0.1.0,
Random Tools 0.1.1, and the 0.1.0 releases of Image, File, EPUB, Archive,
Privacy, Crypto, Barcode, Network, Geo, Helper, Data, Diff, Time, Text, Unicode,
Flow, Subtitle, MIDI, 3D, Query, Scan, Package, Label, Font, Fixture, Minimize,
Format Lab, Repro, Log, Binary, Git, API, Mail, Calendar, Contact,
Diagram, Token, and Device Tools.
Schema Tools is pinned at its hardened v0.1.2 release.
Use
`release/toolbox.lock.example.json` as the template for a future release and
verify every downloaded asset before committing updated values. Artifacts may be:
@@ -157,7 +176,7 @@ npm run assemble -- \
--lock release/toolbox.lock.json \
--portal-dist dist \
--output build/toolbox \
--archive build/add-ideas-toolbox-0.16.0.zip
--archive build/add-ideas-toolbox-0.19.0.zip
```
Existing output is refused. Pass `--force` only when replacing those exact
@@ -180,10 +199,52 @@ build/toolbox/
├── regex/
├── svg/
├── auth/
── sudoku/
── sudoku/
├── colour/
├── office/
├── image/
├── file/
├── epub/
├── archive/
├── privacy/
├── crypto/
├── barcode/
├── network/
├── geo/
├── helper/
├── rand/
├── data/
├── diff/
├── time/
├── text/
├── unicode/
├── flow/
├── subtitle/
├── midi/
├── 3d/
├── query/
├── scan/
├── package/
├── label/
├── font/
├── fixture/
├── minimize/
├── format-lab/
├── repro/
├── schema/
├── log/
├── binary/
├── git/
├── api/
├── mail/
├── calendar/
├── contact/
├── diagram/
├── token/
└── device/
build/add-ideas-toolbox-0.16.0.zip
build/add-ideas-toolbox-0.16.0.zip.sha256
build/add-ideas-toolbox-0.19.0.zip
build/add-ideas-toolbox-0.19.0.zip.sha256
```
The assembler verifies SHA-256 before opening an artifact, validates every app
@@ -204,7 +265,7 @@ directory separately:
```sh
npm run package:static -- \
--input build/toolbox \
--output artifacts/add-ideas-toolbox-0.16.0.zip
--output artifacts/add-ideas-toolbox-0.19.0.zip
```
This also emits a `.sha256` sidecar.
@@ -212,29 +273,34 @@ This also emits a `.sha256` sidecar.
## Local assembled container and publication
`Containerfile` serves only the assembled files with unprivileged nginx on port 8080. It adds restrictive browser headers, same-origin isolation, explicit
`application/javascript` for `.mjs` engine modules and `application/wasm`,
`application/javascript` for `.mjs` engine modules, `application/wasm`, and
`application/gzip` for the bundled Scan OCR language model,
immutable caching only for Vite-hashed assets and narrowly matched
semver-versioned FFmpeg core files, and revalidation for all other files. The
opaque-origin SVG preview iframe loads its packaged controller with a URI-exact
CORS and cross-origin resource-policy exception; all other files retain the
same-origin policy and every normal security header. Camera access is denied on
the shared Toolbox host and granted only to the dedicated
`auth.toolbox.add-ideas.de` origin, where Auth Tools still requests it only
after an explicit user action. If `AUTH_TOOLS_HOST` is customized, update the
exact host entry in `deploy/nginx.conf` and Auth Tools' pinned WebAuthn host at
the same time; the default-deny fallback deliberately does not infer camera
grants from request paths.
Assemble first, then:
same-origin policy and every normal security header. Camera access is denied by
default. It is granted to the dedicated `auth.toolbox.add-ideas.de` origin and,
on the shared Toolbox host, only to `/apps/barcode/`, `/apps/scan/`, and
`/apps/device/`. Device Tools alone additionally receives microphone and screen-
capture policy at its exact path; every probe remains explicitly user initiated.
If `AUTH_TOOLS_HOST` is customized, update
the exact host entry in `deploy/nginx.conf` and Auth Tools' pinned WebAuthn host
at the same time. Every Toolbox app, including Random Tools, is constrained to
same-origin connections. Random Tools implements its random generators locally
with browser APIs and never calls a third-party randomness service.
The packaged policy intentionally does not grant CSP `unsafe-eval`. SaxonJS's
`ixsl:eval()` extension is therefore unsupported in this deployment profile;
normal local XML/XSLT transformations do not require that permission.
Assemble first, then:
```sh
podman build -f Containerfile \
-t git.add-ideas.de/lotobo/toolbox:0.16.0 .
-t git.add-ideas.de/lotobo/toolbox:0.19.0 .
podman run --rm -p 8080:8080 \
git.add-ideas.de/lotobo/toolbox:0.16.0
git.add-ideas.de/lotobo/toolbox:0.19.0
```
For a direct-port local deployment after assembly, use the separate example:
@@ -251,8 +317,8 @@ docker login git.add-ideas.de
docker buildx build \
--platform linux/amd64,linux/arm64 \
--file Containerfile.release \
--tag git.add-ideas.de/lotobo/toolbox:0.16.0 \
--tag git.add-ideas.de/lotobo/toolbox:0.16 \
--tag git.add-ideas.de/lotobo/toolbox:0.19.0 \
--tag git.add-ideas.de/lotobo/toolbox:0.19 \
--push .
```
@@ -274,11 +340,11 @@ needs permission to push code, releases, and container packages to
3. Verify downloaded app assets with `sha256sum -c <asset>.sha256`; copy those
exact values into a reviewed toolbox lock.
4. Run the assembler and serve `build/toolbox` from a nested test path. Open
all eight apps, switch between them, and confirm the encoded `toolbox`
all 50 apps, switch between them, and confirm the encoded `toolbox`
context.
5. Verify the distribution with
`(cd build && sha256sum -c add-ideas-toolbox-0.16.0.zip.sha256)`.
6. Commit the reviewed lock, tag the toolbox release (for example `v0.16.0`), and
`(cd build && sha256sum -c add-ideas-toolbox-0.19.0.zip.sha256)`.
6. Commit the reviewed lock, tag the toolbox release (for example `v0.19.0`), and
push the branch and tag to Gitea.
7. In Gitea, open **Releases → New release**, select the tag, and upload the
static ZIP plus its `.sha256` file. Do not use a mutable “latest” URL in a
@@ -293,69 +359,64 @@ must not re-resolve app versions or substitute a newer release.
## Existing tools
| Tool | State and boundary | Principal workflows | Important concrete scope | Critical considerations and integrations |
| ------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`pdf-tools`** | Existing; dedicated repository | Merge, split, reorder, rotate and export PDF pages | Thumbnail workspace; multi-document operations; ZIP and PDF output; saved local workspace | Workers and IndexedDB; large-document memory control; future signature inspection through `crypto-tools`; metadata and safe-sharing through `privacy-tools` |
| **`xslt-tools`** | Existing; dedicated repository | Develop, test and run XSLT transformations | XML/XSLT editors; transformation results; local files; saved projects; validation and diagnostics | Lazy SaxonJS loading; relocatable assets; useful handoffs to `data-tools`, `schema-tools` and `diff-tools` |
| **`onenote-tools`** | Existing rich-reader release; dedicated repository | Open, browse, inspect and export OneNote sections and packages locally | Desktop/unfragmented FSSHTTPB `.one`/`.onetoc2`; none/LZX/MSZIP/Quantum and multi-cabinet `.onepkg`; trees, rich text, images, tables, ink, attachments and export | Native TypeScript worker with no Wasm; bounded parsing, rendering and export; fragmented FSSHTTP fails safely; no editing or pixel-perfect fidelity |
| **`av-tools`** | Existing local-first v0.3.0 release; dedicated repository | Convert and lightly edit audio and video locally in the browser | Immediate native playback and basic file information; progressive stream inspection on demand; quick conversion; trim, split and crossfade concatenate; crop, resize, normalize, fades, waveform, metadata, chapters, subtitles, scene thumbnails/contact sheets, presets and export | Reviewed ffmpeg.wasm 0.12.10 ST/MT build with verified Opus and bundled label font; bounded queue, temporary storage and resource policy; isolation enables MT with automatic ST fallback; versioned core assets are immutable |
| **`regex-tools`** | Current local-first v0.4.2 release; dedicated repository | Develop, explain, test and apply JavaScript, PCRE2, PHP, Perl, Python, Ruby, Java, C++, Go, .NET, Rust and Scala/JVM-compatible regular expressions | Deterministic syntax trees; engine-native matching, captures and bounded replacement; stable double-buffered live results; PCRE2 tracing and C17 generation; comparison; corpus apply; tests; risk/growth/benchmark analysis; generated cases; bounded minimization; validated ECMAScript formatting; project import/export and optional local persistence | Open-source regexpp and pinned local WebAssembly runtimes for PCRE2, PHP preg, legacy Perl, CPython, CRuby, TeaVM Java/Scala compatibility, libc++ C++, Go, .NET and Rust in killable workers; explicit source/licence inventories, resource limits and engine-specific offset semantics |
| **`svg-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect and edit SVG source, structure, geometry, references and accessibility locally | Synchronized source/tree/canvas/inspector; path and transform tools; reference analysis; optimization; CSS animation preview; exact, sanitized, raster and project export | Untrusted SVG is sanitized into an opaque-origin sandbox; bounded parsing and decompression, explicit security findings and a URI-scoped controller header exception; later milestone slices remain intentionally tracked in the app repository |
| **`auth-tools`** | Current local-first v0.3.0 release; dedicated repository | Generate, migrate and diagnose OTP credentials, and inspect, verify and test WebAuthn/passkey ceremonies locally | HOTP/TOTP/OCRA with time travel, resynchronization and rotation planning; QR, Google, Aegis and encrypted PSKC migration; WebAuthn extension experiments and replayable traces; assertion, attestation, signer-chain and historical metadata-policy evaluation | Authentication material remains memory-only unless explicitly exported; redaction is deliberate but not a secrecy guarantee; live ceremonies and camera scanning are enabled only at the exact dedicated `auth.toolbox.add-ideas.de` origin, while the shared Portal path remains inspect-only; no raw CTAP administration |
| **`sudoku-tools`** | Current local-first v0.2.1 release; dedicated repository | Set, play, generate, analyse and solve classic, Killer and rich variant Sudoku locally | 4×416×16 grids; registry-backed constraint packs including cages, lines, dots, XV, inequalities, indexing and Fog of War; staged hints, candidate maintenance, advanced logical techniques, setter quality checks, mixed-variant generation, source-preserving f-puzzles/SudokuPad interoperability, autosave recovery and searchable local projects | Worker-bounded solving, generation and quality analysis; strict inert imported-visual validation; fog-safe play assistance; IndexedDB history with memory fallback; stable workspace geometry, responsive zoom and pan, a 3×3 standard keypad, tap selection, patterned colours, accessibility controls and an offline-capable PWA shell |
| Tool | State and boundary | Principal workflows | Important concrete scope | Critical considerations and integrations |
| -------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`pdf-tools`** | Existing; dedicated repository | Merge, split, reorder, rotate and export PDF pages | Thumbnail workspace; multi-document operations; ZIP and PDF output; saved local workspace | Workers and IndexedDB; large-document memory control; future signature inspection through `crypto-tools`; metadata and safe-sharing through `privacy-tools` |
| **`xslt-tools`** | Existing; dedicated repository | Develop, test and run XSLT transformations | XML/XSLT editors; transformation results; local files; saved projects; validation and diagnostics | Lazy SaxonJS loading; relocatable assets; useful handoffs to `data-tools`, `schema-tools` and `diff-tools` |
| **`onenote-tools`** | Existing rich-reader release; dedicated repository | Open, browse, inspect and export OneNote sections and packages locally | Desktop/unfragmented FSSHTTPB `.one`/`.onetoc2`; none/LZX/MSZIP/Quantum and multi-cabinet `.onepkg`; trees, rich text, images, tables, ink, attachments and export | Native TypeScript worker with no Wasm; bounded parsing, rendering and export; fragmented FSSHTTP fails safely; no editing or pixel-perfect fidelity |
| **`av-tools`** | Existing local-first v0.3.0 release; dedicated repository | Convert and lightly edit audio and video locally in the browser | Immediate native playback and basic file information; progressive stream inspection on demand; quick conversion; trim, split and crossfade concatenate; crop, resize, normalize, fades, waveform, metadata, chapters, subtitles, scene thumbnails/contact sheets, presets and export | Reviewed ffmpeg.wasm 0.12.10 ST/MT build with verified Opus and bundled label font; bounded queue, temporary storage and resource policy; isolation enables MT with automatic ST fallback; versioned core assets are immutable |
| **`regex-tools`** | Current local-first v0.4.2 release; dedicated repository | Develop, explain, test and apply JavaScript, PCRE2, PHP, Perl, Python, Ruby, Java, C++, Go, .NET, Rust and Scala/JVM-compatible regular expressions | Deterministic syntax trees; engine-native matching, captures and bounded replacement; stable double-buffered live results; PCRE2 tracing and C17 generation; comparison; corpus apply; tests; risk/growth/benchmark analysis; generated cases; bounded minimization; validated ECMAScript formatting; project import/export and optional local persistence | Open-source regexpp and pinned local WebAssembly runtimes for PCRE2, PHP preg, legacy Perl, CPython, CRuby, TeaVM Java/Scala compatibility, libc++ C++, Go, .NET and Rust in killable workers; explicit source/licence inventories, resource limits and engine-specific offset semantics |
| **`svg-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect and edit SVG source, structure, geometry, references and accessibility locally | Synchronized source/tree/canvas/inspector; path and transform tools; reference analysis; optimization; CSS animation preview; exact, sanitized, raster and project export | Untrusted SVG is sanitized into an opaque-origin sandbox; bounded parsing and decompression, explicit security findings and a URI-scoped controller header exception; later milestone slices remain intentionally tracked in the app repository |
| **`auth-tools`** | Current local-first v0.3.1 release; dedicated repository | Generate, migrate and diagnose OTP credentials, and inspect, verify and test WebAuthn/passkey ceremonies locally | HOTP/TOTP/OCRA with time travel, resynchronization and rotation planning; QR, Google, Aegis and encrypted PSKC migration; WebAuthn extension experiments and replayable traces; assertion, attestation, signer-chain and historical metadata-policy evaluation | Authentication material remains memory-only unless explicitly exported; redaction is deliberate but not a secrecy guarantee; live ceremonies and camera scanning are enabled only at the exact dedicated `auth.toolbox.add-ideas.de` origin, while the shared Portal path remains inspect-only; v0.3.1 corrects source provenance and cross-timezone artifact reproducibility; no raw CTAP administration |
| **`sudoku-tools`** | Current local-first v0.2.1 release; dedicated repository | Set, play, generate, analyse and solve classic, Killer and rich variant Sudoku locally | 4×416×16 grids; registry-backed constraint packs including cages, lines, dots, XV, inequalities, indexing and Fog of War; staged hints, candidate maintenance, advanced logical techniques, setter quality checks, mixed-variant generation, source-preserving f-puzzles/SudokuPad interoperability, autosave recovery and searchable local projects | Worker-bounded solving, generation and quality analysis; strict inert imported-visual validation; fog-safe play assistance; IndexedDB history with memory fallback; stable workspace geometry, responsive zoom and pan, a 3×3 standard keypad, tap selection, patterned colours, accessibility controls and an offline-capable PWA shell |
| **`colour-tools`** | Initial local-first v0.1.0 release; dedicated repository | Convert, composite, interpolate, pick, sample, analyse and export colours locally | General colour conversion; arbitrary RGBA compositing; multi-stop colour steps; large visual and native pickers; local image sampling and palette extraction; contrast, gamut and colour-vision-deficiency analysis; harmonies and design-token export | Processing and image access remain local; colour spaces, encoded versus linear-light compositing, interpolation and gamut-mapping assumptions are explicit; mathematical conversion is distinguished from display simulation; integrates with SVG, image and token tools |
| **`office-tools`** | Initial local-first v0.1.0 read-only release; dedicated repository | Open and view word-processing documents, spreadsheets and presentations locally | DOCX, XLSX and PPTX plus ODT, ODS and ODP; document, sheet and slide views with search, outline or thumbnail navigation and zoom; text, tables, images, styles, metadata, cached formula values and presentation notes | Bounded worker-based inert package and XML parsers never execute macros, scripts, formulas, active content or external resources; legacy binary DOC, XLS and PPT are unsupported; viewing is intentionally read-only and does not promise pixel-perfect Office-suite layout fidelity |
| **`image-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, crop, rotate, resize, compare and batch-convert raster images locally | Static JPEG, PNG and WebP; bounded queues; aspect presets; fit/fill/exact resize; PNG/JPEG/WebP export; per-result operation reports | Animated and multi-picture inputs are inspect-only; canvas re-encoding does not preserve arbitrary metadata, ICC profiles, HDR precision or byte identity |
| **`file-tools`** | Initial local-first v0.1.0 release; dedicated repository | Identify, inspect, hash and inventory local files | Signature and claimed-MIME comparison; paged hex/ASCII and string views; SHA-256/SHA-512; deterministic JSON/CSV manifests; duplicate candidates | Detection and entropy are heuristics rather than validation or malware analysis; v0.1 intentionally does not mutate, split, join or rename files |
| **`epub-tools`** | Initial local-first v0.1.0 release; dedicated repository | Read, inspect, validate and repair EPUB 2/3 publications | Package, metadata, spine, EPUB 3 nav and EPUB 2 NCX views; sandboxed reading; link checks; metadata and cover editing; text/chapter/report export; normalized rebuilds | Strict bounded ZIP and XML handling; active and external content are blocked; DRM is detected but never bypassed; focused preflight is not a complete EPUBCheck implementation |
| **`archive-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, create, compare and safely extract archive content | ZIP/ZIP64, TAR/USTAR/PAX, gzip and tar.gz; inert previews; deterministic ZIP/TAR output; cross-format inventory comparison; selected-file repackaging | Path, entry-count, expanded-size and compression-ratio limits; no direct filesystem restoration, nested expansion, encrypted or multipart ZIP support; links and special entries are blocked |
| **`privacy-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect image metadata and make independently verified sharing copies | Deep JPEG, PNG and WebP scans for EXIF/IPTC/XMP/profiles/previews/provenance and trailing data; orientation-normalized pixel re-encoding; source/output hashes; JSON and ZIP reports | Not an anonymity guarantee; static supported images only; re-encoding can change pixels and remove colour, resolution and authenticity information; reports can themselves contain sensitive metadata |
| **`crypto-tools`** | Initial local-first v0.1.0 inspection release; dedicated repository | Inspect certificate, request, revocation-list, key and JWK material | Bounded PEM/DER X.509, CSR and CRL inspection; public/private key identification; JWK/JWKS warnings and RFC 7638 thumbprints; explicit issuer-signature links; DNS SAN hostname checks | No browser/OS trust implication, complete RFC 5280 path validation, revocation service, issuance, key generation, private-key decryption or general signature verification |
| **`barcode-tools`** | Initial local-first v0.1.0 release; dedicated repository | Generate and decode QR codes and common barcodes | SVG QR, Data Matrix, PDF417, Aztec and selected linear formats; bounded image or opt-in camera decode; structured QR payloads; CSV batch ZIP; GTIN and quiet-zone assistance | Decoded payloads remain inert text and are never opened automatically; camera is path-scoped and user initiated; generated output, GS1 allocation and print quality still require applicable interoperability checks |
| **`network-tools`** | Initial offline v0.1.0 release; dedicated repository | Calculate IP networks and construct or inspect common network values | IPv4/IPv6 canonicalization and CIDR ranges; URL/query parsing without navigation; DNS-record construction; response-header inspection; CSP builder; MIME reference | Performs no DNS, URL, HTTP or scanning request; pasted values remain bounded and inert; results are construction and calculation aids rather than live network observations |
| **`geo-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, convert, simplify and analyse geospatial files | GeoJSON, GPX, KML and coordinate CSV; WGS 84 bounds, distance and elevation; DouglasPeucker simplification; decimal/DMS conversion; coordinate-only sketch | Small Point/LineString/Polygon model with scalar properties; conversion losses are explicit; no CRS transformation, basemap request or survey-grade claim |
| **`helper-tools`** | Initial v0.1.0 app and reusable package release | Encode, convert, inspect and calculate with shared bounded primitives | Base/byte/text/URL conversion; Unicode and line transforms; exact number and unit conversion; hashes; CIDR; timestamps; hardened JSON/CSV; secure and seeded random primitives; deep-linked calculator workspaces | Framework-free `@add-ideas/toolbox-helpers` package is consumed directly by eleven v0.1 apps; operations disclose strictness, limits and non-cryptographic seeded boundaries |
| **`rand-tools`** | Local-only v0.1.1 release; dedicated repository | Generate secure or reproducible random values through focused workspaces | Unbiased WebCrypto integers/strings; seeded reproducible generation; UUIDv4/v7 and ULID; dice; sampling, shuffle, passphrases and normal distribution; all generators run entirely in the browser | Secure local generation never falls back; deterministic output is reproducible rather than secret; the app makes no third-party randomness request and the Portal grants it no external network destination |
| **`data-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, format, query, flatten and convert structured data | JSON, YAML 1.2, TOML, XML, CSV, TSV and NDJSON; exact JSON numbers; bounded tree/table/leaf views; JSON Pointer and safe path queries; all-format conversion with loss/coercion reports; spreadsheet-formula neutralization | Disposable bounded parser worker; rejects active XML constructs and unsafe object keys; conversions surface information loss and round-trip instability |
| **`diff-tools`** | Initial local-first v0.1.0 release; dedicated repository | Compare text, JSON, XML and delimited data semantically | Line/word/code-point/grapheme text diff; exact newline state; object-aware exact-number JSON and RFC 6902; namespace-aware XML rules; keyed CSV/TSV; unified/side-by-side views and portable reports | Normalization settings and ignored distinctions remain visible; bounded disposable worker; v0.1 intentionally excludes images, binary documents, directories and archives |
| **`time-tools`** | Initial local-first v0.1.0 release; dedicated repository | Convert timestamps and explore zones, arithmetic and recurrence | Exact signed nanosecond epochs; IANA-zone comparisons and DST ambiguity; wall-clock versus elapsed arithmetic; bounded cron and RRULE previews; business days; escaped UTC ICS export | Uses the browser's IANA data and does not model leap seconds; regional holidays are never inferred; recurrence and skipped/ambiguous local-time choices are explicit |
| **`text-tools`** | Initial local-first v0.1.0 release; dedicated repository | Build ordered, inspectable plain-text transformation pipelines | Line endings, trimming, whitespace, sort/deduplicate, locale case, Unicode normalization, transliteration, escapes, wrapping, columns, explicit file decoding and versioned recipes | Exact source/result and per-step changes stay visible; compatibility normalization, transliteration, narrow encodings and selected transforms warn when they may be lossy |
| **`unicode-tools`** | Initial local-first v0.1.0 release; dedicated repository | Search and inspect Unicode characters, emoji, scripts, text and confusables | Checksum-pinned Unicode 17.0 catalogue; character/alias/code-point search; emoji and named sequences; UTF-8/UTF-16/escape inspection; grapheme segmentation; normalization; UTS #39 skeleton; selected Unihan fields; symbol collections | Official Unicode data is redistributed under Unicode-3.0 and is not scraped from symbol sites; private-use and surrogate ranges are not misrepresented as assigned characters; confusable and mixed-script results are review signals, not security verdicts |
| **`flow-tools`** | Initial local-first v0.1.0 release; dedicated repository | Design and run deterministic structured-data pipelines | Bounded JSON, CSV, NDJSON and XML sources; select, rename, filter, map, sort, group, join, format and export stages; inspectable snapshot and loss notes at every stage; portable validated recipes | 2 MiB sources, 10,000 input rows, 20,000 join rows, 200 fields and 30 stages; no arbitrary code, eval, plug-in or network stage |
| **`subtitle-tools`** | Initial local-first v0.1.0 release; dedicated repository | Edit, validate, synchronize, compare and convert captions | Bounded SRT, WebVTT and ASS/SSA; cue editing, shift/stretch and frame-rate conversion; editorial diagnostics; revision comparison; local media playback and waveform peaks | Preserves format-specific information where possible and reports cross-format loss; no speech recognition, automatic alignment, semantic comparison or pixel-perfect ASS rendering |
| **`midi-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, visualize, edit, audition and export Standard MIDI files | SMF type 0/1 events, tempo/time/key timelines, piano roll; transpose, quantize, tempo, crop and channel operations; deterministic MIDI/CSV/JSON export; Web Audio sine preview | 8 MiB, 256-track and 250,000-event caps; PPQN only; bounded preview is not a General MIDI instrument or soundfont renderer; editing semantics are explicit |
| **`3d-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, preview, repair and export triangle meshes | OBJ, binary/ASCII STL, ASCII/binary little-endian PLY and glTF/GLB 2; mesh statistics; capped WebGL preview; normal repair and transform baking; normalized OBJ/STL export | 32 MiB and one-million-vertex/triangle caps; glTF is an embedded, static TRIANGLES subset with no external assets, sparse accessors, animation, skins, texture or compression decoding; source material graphs and node transforms are not recreated |
| **`query-tools`** | Initial local-first v0.1.0 release; dedicated repository | Query structured local data through bounded row and path languages | JSON, CSV, NDJSON and inert XML; focused SQL-like select/filter/group/aggregate/sort/limit; JSONPath-like property/index/wildcard/filter paths; table, tree and JSON results; saved queries and export | Not full SQL, JSONPath or JMESPath compatibility; 2 MiB, 10,000-row/value, 200-field and 200,000-node caps; XML DTD/entities and code evaluation are rejected |
| **`scan-tools`** | Initial local-first v0.1.0 release; dedicated repository | Correct photographed pages, run optional OCR and assemble local output | Up to 24 PNG/JPEG/WebP pages; perspective correction, rotate/deskew, tonal and threshold controls; reorder; image and PDF export; bundled same-origin English Tesseract model | Camera is exact-path and opt-in; strict pixel/byte/page caps; OCR is memory-heavy and not an accuracy guarantee; no PDF input, automatic corners, handwriting guarantee, shadow/finger removal or searchable PDF text layer |
| **`package-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect and compare ZIP/ZIP64 compound packages | Package trees and ZIP risk diagnostics; EPUB, OOXML, ODF, JAR, APK and WebExtension adapters; relationships/manifests; media preview/download; signature-material inventory; inventory comparison/export | Inspection does not render specialized formats, decode APK signing blocks or establish signature validity/trust; encrypted, split, unsafe, unsupported or over-budget entries remain inventory-only |
| **`label-tools`** | Initial local-first v0.1.0 release; dedicated repository | Merge local records into printable labels, badges and asset tags | CSV/JSON mapping; serial/random values; local raster assets; QR and common 1D/2D barcodes; mm/in/pt stock and custom grids; calibration/marks; paginated preview; SVG, ZIP and 144-DPI PDF export | 2 MiB/2,000-row/100-field data bounds and bounded images/pages; stock names are geometries, not vendor certification; system fonts are not embedded and PDF is rasterized, not archival/press quality |
| **`font-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, compare, preview and prepare local fonts | TTF, OTF and WOFF metadata/tables, Unicode coverage, variable axes, fallbacks and embedding signals; arbitrary-text sandbox; safe CSS; rights-confirmed static glyf/CFF subset with loss report | Disposable worker and strict file/table/glyph bounds; WOFF2/TTC unsupported; fsType is a technical signal, not legal advice; no variable flattening or shaping/composite closure, and subsetting discards advanced tables |
| **`fixture-tools`** | Initial local-first v0.1.0 release; dedicated repository | Generate deterministic synthetic test fixtures | Focused JSON Schema, SQL DDL, XSD, CSV-heading and portable-model import; relationships, distributions, boundaries and deliberate violations; JSON/CSV/NDJSON/XML/SQL/recipe export | Importers are documented subsets; 2 MiB input, 20 tables, 100 fields/table, 50,000 rows and bounded output; synthetic data is not anonymization and seeded output is reproducible, not secret |
| **`minimize-tools`** | Initial local-first v0.1.0 release; dedicated repository | Reduce failing inputs while continuously preserving a selected predicate | Line/token/code-point and structure-aware JSON/XML reduction; literal, invalid syntax, regex, focused JSON Schema and local XSLT predicates; budgets, cancellation, trace and report export | Produces a locally minimal attempted case, not a globally shortest one; focused schema/XSLT subsets fail closed; 2 MiB, 2,000-test and 30-second caps, with a disposable one-second regex worker |
| **`format-lab`** | Initial local-first v0.1.0 release; dedicated repository | Explore conversion paths and measure representative round-trip loss | Conservative data/image/AV/subtitle format graphs; executable JSON/NDJSON/CSV/typed-XML record conversion; property selection, path ranking, round-trip evidence and deterministic reports | Media graphs plan handoffs rather than duplicate codecs; executable lab handles bounded records, not arbitrary documents; catalogue expectations are not file measurements and untested properties remain explicit |
| **`repro-tools`** | Initial local-first v0.1.0 release; dedicated repository | Build, compare, sign and package reproducible local file inventories | SHA-256/SHA-512 manifests; deterministic path ordering and JSON/CSV; reference comparison; fixed-metadata ZIP; optional memory-only P-256 signature envelope | 64 MiB/file, 256 MiB/selection and 10,000-entry caps; ZIP is capped at 128 MiB; signatures prove integrity relative to an independently authenticated public key and are intentionally not byte-reproducible |
| **`schema-tools`** | Hardened local-first v0.1.2 release; dedicated repository | Inspect, validate, compare and derive examples from schema workspaces | Local JSON Schema/OpenAPI reference graphs; focused JSON Schema validation; OpenAPI operation/sample/change analysis; XSD, Relax NG and Schematron structure; bounded heuristic XML samples | Remote/escaping references, entities, code and XPath are blocked; JSON Schema/OpenAPI support is a documented subset, while XML languages receive structural inspection rather than complete instance validation; shared work/node/depth/text/output budgets, linear cached traversal and well-formed XML fallbacks are regression-tested |
| **`log-tools`** | Initial local-first v0.1.0 release; dedicated repository | Stream, inspect, correlate, redact and export large logs | Incremental UTF-8 file scan; plain, JSONL, nginx, syslog and logfmt parsing; normalized fields, aggregation, search/filter; deterministic redaction recipes; CSV/NDJSON/text export | Eight-GiB gate and five-million-line stop without whole-file strings; only a bounded 10,000-record/32 MiB preview supports search, redaction and export; parsers and autodetection are focused/heuristic |
| **`binary-tools`** | Initial local-first v0.1.0 release; dedicated repository | Convert, inspect and decode byte-oriented values | Synchronized UTF-8/hex/Base64/Base32/Base58; paged byte inspector; CBOR and MessagePack; strict DER tree; Protocol Buffers wire view with optional scalar/nested schema | Inert, no requests or evaluation; 1 MiB, depth-64 and 10,000-node bounds; Base58 capped at 4 KiB; protobuf groups and a complete generated runtime are out of scope |
| **`git-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect and author Git interchange text without repository access | Unified/git patch parse, stats and bounded before/after authoring; root `.gitignore` matcher with explanations; SemVer compare/ranges; Conventional Commit builder/lint; changelog normalization | Patch/matrix/count bounds; ignore matching covers one root file, not nested/global/index state; SemVer and changelog behavior is intentionally focused; no workspace or `.git` access |
| **`api-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect and compare OpenAPI descriptions and saved HTTP evidence | Bounded JSON/YAML OpenAPI 3.0/3.1; local multi-file `$ref`; navigation, samples, examples and security inventory; inert curl/Fetch/Python text; conservative change report; HAR/exchange summaries | Never executes HTTP, follows URLs, resolves remote references or stores credentials; focused validation/sample generation is not a complete validator, code generator, client, proxy or security scanner |
| **`mail-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, compare, download and redact EML/MIME content | Folded/RFC 2047 headers; bounded multipart/nested-message tree; Base64/quoted-printable; text and opaque sandboxed sanitized HTML; attachment inventory/download; auth-header diagnostics; canonical/redacted export | Remote and active HTML content is removed and never loaded; no mailbox, server, decryption, DKIM verification, identity, malware or anonymity claim; bounded normalization does not promise byte identity |
| **`calendar-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, repair, merge and reconcile iCalendar data | RFC 5545 events/metadata/attendees/timezones; bounded recurrence preview; duplicate/overlap diagnostics; UID/RECURRENCE-ID merge; conservative canonical repair; DST transition/gap/overlap evidence | 4 MiB, line/component/event and recurrence-horizon caps; browser IANA data and focused recurrence interpretation are evidence rather than a complete calendar-server implementation |
| **`contact-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect, edit, convert and reconcile sensitive contacts | vCard 3/4 parsing/editing/export; inferred reviewable CSV mapping; duplicate candidates and conflict-reporting merge; bounded local vCard QR; masked overview and memory clearing | 2 MiB, 50,000-line and 2,000-contact caps; binary/quoted-printable values are diagnosed rather than decoded and unsupported properties are not silently round-tripped; no persistence or telemetry |
| **`diagram-tools`** | Initial local-first v0.1.0 release; dedicated repository | Author safe deterministic text diagrams and export accessible graphics | Independent Mermaid-like flow/graph, sequence, class and state subset; diagnostics, pan/zoom, SVG/2× PNG and textual outline | Not full Mermaid or Graphviz; directives, clicks, styles, scripts, HTML and remote assets are rejected; 50,000-character, 2,000-line, 200-node, 500-edge and 20-megapixel caps |
| **`token-tools`** | Initial local-first v0.1.0 release; dedicated repository | Edit, validate, theme and export design tokens | W3C-style nested JSON plus local sets/themes; alias resolution and cycle/type diagnostics; colour, dimension, typography, shadow and scalar values; JSON, CSS, Sass, Android and Swift export with loss report | The set/theme wrapper is app-specific; 1 MiB, depth-64 and 10,000-token bounds; unknown/conflicting shapes fail explicitly and platform composite losses are never silently omitted |
| **`device-tools`** | Initial local-first v0.1.0 release; dedicated repository | Inspect browser capability evidence without creating a device fingerprint | Passive context/display/input/accessibility/media/storage/PWA/API inventory; opt-in permission, storage, WebGL/WebGPU, media, battery, network, camera, microphone and screen probes; redacted reports | No identifier, score, high-entropy report, recording, persistence or passive prompt; sensitive probes are exact-path, individually initiated and immediately stop returned tracks; results are capability evidence, not a reliability guarantee |
## Planned tools
| Tool | State and boundary | Principal workflows | Important concrete scope | Critical considerations and integrations |
| -------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`flow-tools`** | Later platform layer | Compose local processing operations across tools | Example: CSV → filter → QR generation → SVG template → PDF → ZIP; reusable recipes; typed inputs and outputs; progress and cancellation | Do not load complete React applications into one runtime; expose separate worker-safe operation packages only after several apps have stable operations |
| **`file-tools`** | High priority; dedicated repository | Identify, inspect and organize local files | Magic-byte detection; hex view; decoded strings; checksums; directory manifests; split/join; duplicate detection; trailing-data detection; batch-rename preview | All inputs are untrusted; format inspectors require strict size and nesting limits; natural entry point to archive, privacy, crypto and package tools |
| **`image-tools`** | High priority; dedicated repository | Edit and batch-process raster images | Crop, resize, rotate, compress, convert, contact sheets, sprites, responsive sets, favicon generation, metadata removal and visual quality comparison | Use workers and off-main-thread rendering; preserve or deliberately remove colour profiles; integrate with colour, SVG, PDF and privacy tools |
| **`subtitle-tools`** | Medium priority; dedicated repository | Edit, validate and synchronize captions | SRT, WebVTT and ASS; timing shifts; stretching; frame-rate conversion; overlap and reading-speed checks; waveform synchronization; revision comparison | Direct integration with `av-tools`; preserve style information when supported and disclose conversion losses |
| **`midi-tools`** | Medium specialist app | MIDI event inspection and editing; transpose, quantize, tempo maps and controller data; device access should remain optional | |
| **`3d-tools`** | Large specialist app | Inspect STL, OBJ and glTF; dimensions, bounding boxes, mesh simplification and common geometry defects; worker/GPU use and file limits | |
| **`query-tools`** | High-value but large; dedicated repository | Analyse local tabular and relational data with SQL | CSV, JSON, NDJSON, Parquet and SQLite; schema inference; joins; aggregation; pivots; charts; export to common data formats | WASM memory and streaming; distinguish this analytical product from document-oriented `data-tools`; query work must remain local |
| **`epub-tools`** | Medium app | EPUB inspection, metadata and cover editing, link validation, chapter extraction and structural repair; sanitize embedded HTML and SVG | |
| **`scan-tools`** | Large app | Camera/document correction; crop, deskew and threshold; page assembly; local OCR; PDF output; model downloads and memory use must be explicit | |
| **`office-tools`** | Medium-to-large app | Inspect rather than reproduce an office suite: package structure, relationships, metadata, comments, embedded images and basic repairs | |
| **`package-tools`** | Medium priority | Inspect compound and package-based formats | EPUB; DOCX/XLSX/PPTX; ODF; JAR; APK; browser extensions; package trees; manifests; relationships; embedded media; signatures; orphaned parts | Generic container inspector with format adapters; complements rather than replaces `onenote-tools`, `epub-tools` and `office-tools` |
| **`archive-tools`** | Medium-to-high priority; dedicated repository | Inspect, create, compare and extract archives | ZIP, TAR, gzip and selected additional formats; selective extraction; content preview; deterministic archives; timestamp normalization; archive comparison | Expansion-ratio, entry-count and total-size limits; traversal-safe extraction; never execute extracted files |
| **`privacy-tools`** | High priority; dedicated repository | Inspect and remove metadata before sharing | EXIF and GPS; document author/comments; embedded thumbnails; PDF metadata and attachments; hidden package entries; AV tags; personal filenames; structured safe-sharing report | Never promise absolute anonymity; explicitly state inspected, removed, preserved and unsupported structures; integrate with most file-oriented apps |
| **`crypto-tools`** | Planned; dedicated repository | Inspect keys, certificates and signatures; validate chains | X.509 PEM/DER, CSR, CRL, PKCS #8, encrypted PKCS #8, PKCS #12/PFX, JWK/JWKS; key/certificate matching; path construction; hostname, purpose and time checks; CMS/JWS later | Inspection-first; explicit trust anchors; no implication that browser/OS trust stores are used; no private-key persistence; offline revocation first; network checks opt-in; restrictive CSP and worker isolation |
| **`barcode-tools`** | Planned; dedicated repository | Generate, inspect and decode QR and barcodes | QR, common one- and two-dimensional codes; camera/image decoding; GS1 assistance; CSV batch generation; quiet-zone and print-size checks; structured payload builders | Treat decoded payloads as untrusted; never open links automatically; camera permission must be optional; integrate with `label-tools`, `contact-tools` and `crypto-tools` |
| **`label-tools`** | Medium priority; dedicated repository | Generate labels and badges from templates and data | CSV/JSON merge into SVG templates; QR/barcode fields; serial numbers; A4 label sheets; badges; asset tags; cut marks; calibration | Strong suite demonstration linking data, SVG, barcode, random and PDF capabilities; print dimensions must be explicit and testable |
| **`font-tools`** | Medium priority; dedicated repository | Inspect, preview and prepare fonts | Glyph coverage; variable axes; metadata; fallback comparison; subsetting; CSS generation; arbitrary-text previews | Font licensing and embedding restrictions must be visible; use untrusted-font isolation and strict parser limits |
| **`fixture-tools`** | Medium priority | Generate deterministic test data | JSON Schema, XSD, SQL DDL, CSV headings or interactive models to JSON, CSV, XML, SQL and NDJSON; foreign keys; distributions; boundary and invalid cases | Seeded reproducibility; uniqueness constraints; privacy-safe synthetic data; natural extension of `rand-tools` |
| **`minimize-tools`** | Distinctive specialist tool | Reduce a failing input while preserving a failure | Minimize XML triggering an XSLT error; shortest regex pathological input; smallest JSON schema failure; selectable failure predicates | Expensive repeated execution must be bounded and cancellable; record the exact predicate and transformation versions |
| **`format-lab`** | Later, distinctive product | Explore conversion paths and information loss | Format graph; round-trip tests; property preservation; type coercion; metadata loss; recommended path selection across data, image, AV and subtitle formats | No conversion should be described as lossless without testing relevant properties |
| **`repro-tools`** | Medium-to-later | Create manifests and provenance records | File hashes; directory manifests; operation history; tool/version/parameter records; deterministic package creation; verification reports | Useful foundation for reproducible workflows and signed manifests; integrates with crypto, archive and flow tools |
| **`schema-tools`** | Dedicated specialist app | Validate, inspect and generate examples for JSON Schema, XSD, Relax NG, Schematron and OpenAPI; visualize references and incompatibilities | |
| **`log-tools`** | Dedicated app | Stream and filter large logs; parse common formats; correlate records; build timelines; extract fields; anonymize values; avoid loading the complete file into memory | |
| **`network-tools`** | Helper family or small app | IPv4/IPv6 subnetting; CIDR ranges; URL and query parsing; DNS-record construction; HTTP headers; CSP generation; MIME lookup; avoid turning it into an intrusive scanner | |
| **`binary-tools`** | Dedicated specialist app | Base64, hexadecimal, CBOR, MessagePack, ASN.1 and Protocol Buffers; schema-assisted decoding; byte-range highlighting; strict depth and size limits | |
| **`git-tools`** | Small-to-medium app | Patch inspection and editing; `.gitignore` testing; semantic-version comparison; conventional commits; changelog normalization; no repository-hosting dependency | |
| **`api-tools`** | Medium app | OpenAPI validation; request and response examples; curl and client-command generation; saved HTTP-exchange inspection; direct browser requests remain subject to CORS | |
| **`mail-tools`** | Medium app | EML and MIME inspection; header analysis; attachment extraction; body-part comparison; HTML mail must be heavily sandboxed | |
| **`calendar-tools`** | Small-to-medium app | ICS inspection, merging, deduplication, repair, recurrence visualization and timezone diagnostics | |
| **`contact-tools`** | Small-to-medium app | vCard inspection and editing; CSV mapping; deduplication; contact QR generation; treat all contact data as sensitive | |
| **`geo-tools`** | Medium app | GeoJSON, GPX, KML and coordinate CSV; format conversion; track simplification; distance/elevation analysis; coordinate-reference assumptions must be explicit | |
| **`diagram-tools`** | Medium app | Code and visual editing for Mermaid, Graphviz and related representations; renderers require sanitization and sandboxing | |
| **`token-tools`** | Small-to-medium app | Design-token editing and conversion between JSON, CSS custom properties, Sass, Android and iOS forms; integrate with colour and SVG tools | |
| **`device-tools`** | Specialist app | Serial terminal, sensor logger, microcontroller console and controlled firmware installation; explicit permission and browser-capability checks | |
## Planned helpers
Helpers export funcionality for other tools to use. They may also present a tool surface to be used directly
| Tool | State and boundary | Principal workflows | Important concrete scope | Critical considerations and integrations |
| ------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **`helpers-tools`** | One shared artifact with deep links | Stateless Base64, URL encoding, case conversion, number bases, Unicode code points, unit conversion, small checksums, subnet and timestamp calculators; avoid a repository per calculator | |
| **`colour-tools`** | Planned; small-to-medium dedicated repository | Colour conversion, calculation and palette work | sRGB, Display P3, Lab, LCH, OKLab and OKLCH; gamut mapping; contrast; colour-vision simulation; gradients; palette extraction; design-token export | Make colour-space assumptions explicit; distinguish mathematical conversion from display simulation; integrate with SVG, image and token tools |
| **`rand-tools`** | Planned; small dedicated repository | Generate random numbers, strings, identifiers and samples | Cryptographically secure generation; deterministic seeded generation; UUIDs, ULIDs, passphrases, dice notation, distributions, weighted selection and shuffling | Clearly separate secure randomness from reproducible pseudorandomness; no misleading “strength” claims; natural foundation for `fixture-tools` |
| **`data-tools`** | High priority; dedicated repository | Inspect, edit, validate, query and convert structured data | JSON, YAML, TOML, XML, CSV and NDJSON; tree/table/source views; schema inference; flattening; filtering; field mapping; JSONPath-style queries; conversion recipes | Every conversion should disclose information loss, coercion and round-trip instability; XML-specialist workflows hand off to `xslt-tools` |
| **`diff-tools`** | High priority; dedicated repository or shared engine plus UI | Compare documents and files semantically | Text; JSON object-aware comparison; XML normalization; CSV keyed comparison; images with overlay/heatmap; archives and directories; PDF pages; optional audio waveform comparison | Normalization and ignored properties must be visible; produce portable reports and standard patch formats where possible |
| **`text-tools`** | Medium priority; one app with deep-linked panels | Transform and normalize plain text | Unicode normalization; line-ending conversion; encoding; sorting; deduplication; case changes; transliteration; escaping; column operations; transformation pipelines | Preserve exact input/output visibility; warn about lossy encodings and Unicode confusables; integrate regex operations |
| **`time-tools`** | Medium priority; small dedicated app or helper family | Work with dates, timestamps, time zones and recurrences | Unix timestamps; date arithmetic; durations; ISO 8601; timezone comparison; cron; RRULE; ICS generation; business days; DST-transition visualization | Visualize actual recurrence instances and ambiguous/skipped local times; do not rely on simplified fixed-offset calculations |
No unreleased applications are currently listed here. New ideas should be added
only after their intended local-processing boundary and first honest release
scope are documented; shipped applications remain in the Existing tools table.
## Licensing
+1 -1
View File
@@ -3,7 +3,7 @@ services:
build:
context: .
dockerfile: Containerfile
image: git.add-ideas.de/lotobo/toolbox:0.16.0
image: git.add-ideas.de/lotobo/toolbox:0.19.0
restart: unless-stopped
read_only: true
ports:
+3 -3
View File
@@ -6,9 +6,9 @@ services:
context: .
dockerfile: Containerfile.release
args:
TOOLBOX_RELEASE_VERSION: "${TOOLBOX_RELEASE_VERSION:-0.16.0}"
TOOLBOX_RELEASE_SHA256: "${TOOLBOX_RELEASE_SHA256:-2ae120dd54196428893420a236b32ee260a08af3e0d390362da3457d85110f4e}"
image: "git.add-ideas.de/lotobo/toolbox:${TOOLBOX_RELEASE_VERSION:-0.16.0}"
TOOLBOX_RELEASE_VERSION: "${TOOLBOX_RELEASE_VERSION:-0.19.0}"
TOOLBOX_RELEASE_SHA256: "${TOOLBOX_RELEASE_SHA256:-b6003d8b3eee8a13032527b014a381d832ba46108c35d0aee9e1cfa6a1b281e2}"
image: "git.add-ideas.de/lotobo/toolbox:${TOOLBOX_RELEASE_VERSION:-0.19.0}"
restart: unless-stopped
read_only: true
tmpfs:
+14 -4
View File
@@ -14,9 +14,12 @@ map $uri $toolbox_access_control_allow_origin {
"/apps/svg/canvas-frame-controller.js" "*";
}
map $host $toolbox_permissions_policy {
default "camera=(), microphone=(), geolocation=(), payment=(), usb=()";
"auth.toolbox.add-ideas.de" "camera=(self), microphone=(), geolocation=(), payment=(), usb=()";
map "$host:$uri" $toolbox_permissions_policy {
default "camera=(), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";
"~^auth\.toolbox\.add-ideas\.de:" "camera=(self), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";
"~^[^:]+:/apps/barcode(?:/|$)" "camera=(self), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";
"~^[^:]+:/apps/scan(?:/|$)" "camera=(self), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";
"~^[^:]+:/apps/device(?:/|$)" "camera=(self), microphone=(self), display-capture=(self), geolocation=(), payment=(), usb=()";
}
server {
@@ -37,7 +40,7 @@ server {
add_header Cross-Origin-Resource-Policy $toolbox_resource_policy always;
add_header Access-Control-Allow-Origin $toolbox_access_control_allow_origin always;
add_header Permissions-Policy $toolbox_permissions_policy always;
add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; media-src 'self' blob:; font-src 'self' data:; connect-src 'self'; worker-src 'self' blob:; manifest-src 'self'" always;
add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; media-src 'self' blob:; font-src 'self' data: blob:; connect-src 'self'; worker-src 'self' blob:; manifest-src 'self'" always;
add_header Cache-Control $toolbox_cache_control always;
gzip on;
@@ -63,6 +66,13 @@ server {
try_files $uri =404;
}
location ~* ^/apps/scan/ocr/lang/[a-z0-9_-]+\.traineddata\.gz$ {
types {
application/gzip gz;
}
try_files $uri =404;
}
location ~* \.(?:css|js|mjs|woff2?|png|jpe?g|gif|webp|svg|ico|webmanifest)$ {
try_files $uri =404;
}
+15 -15
View File
@@ -1,12 +1,12 @@
{
"name": "@add-ideas/toolbox-portal",
"version": "0.2.18",
"version": "0.2.22",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@add-ideas/toolbox-portal",
"version": "0.2.18",
"version": "0.2.22",
"license": "AGPL-3.0-only",
"dependencies": {
"@add-ideas/toolbox-contract": "^0.2.3",
@@ -2031,9 +2031,9 @@
}
},
"node_modules/brace-expansion": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
"integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3432,9 +3432,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.16",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
"integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
@@ -3609,9 +3609,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.20",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.20.tgz",
"integrity": "sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==",
"version": "8.5.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
"integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
"dev": true,
"funding": [
{
@@ -3629,7 +3629,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.16",
"nanoid": "^3.3.17",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -4166,9 +4166,9 @@
}
},
"node_modules/undici": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz",
"integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==",
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
"integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
"dev": true,
"license": "MIT",
"engines": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@add-ideas/toolbox-portal",
"version": "0.2.18",
"version": "0.2.22",
"license": "AGPL-3.0-only",
"private": true,
"type": "module",
+2 -2
View File
@@ -1,8 +1,8 @@
# Corresponding source
The source code corresponding to add·ideas Toolbox Portal 0.2.18 is available at:
The source code corresponding to add·ideas Toolbox Portal 0.2.22 is available at:
https://git.add-ideas.de/lotobo/toolbox-portal/src/tag/v0.16.0
https://git.add-ideas.de/lotobo/toolbox-portal/src/tag/v0.19.0
Each bundled application contains its own `SOURCE.md`, license, and third-party
license materials. The application sources are also linked from the portal.
+168
View File
@@ -40,6 +40,174 @@
{
"manifest": "./apps/sudoku/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/colour/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/office/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/image/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/file/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/epub/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/archive/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/privacy/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/crypto/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/barcode/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/network/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/geo/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/helper/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/rand/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/data/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/diff/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/time/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/text/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/unicode/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/flow/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/subtitle/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/midi/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/3d/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/query/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/scan/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/package/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/label/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/font/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/fixture/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/minimize/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/format-lab/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/repro/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/schema/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/log/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/binary/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/git/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/api/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/mail/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/calendar/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/contact/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/diagram/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/token/toolbox-app.json",
"enabled": true
},
{
"manifest": "./apps/device/toolbox-app.json",
"enabled": true
}
]
}
+299 -5
View File
@@ -1,8 +1,8 @@
{
"$schema": "./toolbox-release-lock.schema.json",
"schemaVersion": 1,
"releaseVersion": "0.16.0",
"portalVersion": "0.2.18",
"releaseVersion": "0.19.0",
"portalVersion": "0.2.22",
"catalogue": {
"id": "de.add-ideas.toolbox",
"name": "add·ideas Toolbox",
@@ -57,9 +57,9 @@
},
{
"id": "de.add-ideas.auth-tools",
"version": "0.3.0",
"artifact": "https://git.add-ideas.de/lotobo/auth-tools/releases/download/v0.3.0/auth-tools-0.3.0.zip",
"sha256": "ac80a711a0fc00d554505e6278aa3557eca4248b6da2ac9e2bae74bc0b26e58e",
"version": "0.3.1",
"artifact": "https://git.add-ideas.de/lotobo/auth-tools/releases/download/v0.3.1/auth-tools-0.3.1.zip",
"sha256": "60e90492fb50d2ce23298b3a3af84b1e3be02bbf5dea01d478f889d65eb66f3a",
"target": "auth"
},
{
@@ -68,6 +68,300 @@
"artifact": "https://git.add-ideas.de/lotobo/sudoku-tools/releases/download/v0.2.1/sudoku-tools-0.2.1.zip",
"sha256": "3987813a3bcd24056b9ca9607ba5d74a094d54c15b0e8a7966df7373e87df67a",
"target": "sudoku"
},
{
"id": "de.add-ideas.colour-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/colour-tools/releases/download/v0.1.0/colour-tools-0.1.0.zip",
"sha256": "c933f506362709a031a5cd830657604510b8e4ccb1800be77d40d0eee256490b",
"target": "colour"
},
{
"id": "de.add-ideas.office-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/office-tools/releases/download/v0.1.0/office-tools-0.1.0.zip",
"sha256": "3f950a413c74bae3b8f190954272fd91c9b141aab4fa50c936d5ad3741539aaf",
"target": "office"
},
{
"id": "de.add-ideas.image-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/image-tools/releases/download/v0.1.0/image-tools-0.1.0.zip",
"sha256": "8aa67d0c3cfd1060c261e9be108fb443384aaec95f82d3c1b96b63b2d07963e1",
"target": "image"
},
{
"id": "de.add-ideas.file-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/file-tools/releases/download/v0.1.0/file-tools-0.1.0.zip",
"sha256": "9225ff60c639d563bb514ac390b5b2cbad4b8030a070e6398e7c200763c5f89e",
"target": "file"
},
{
"id": "de.add-ideas.epub-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/epub-tools/releases/download/v0.1.0/epub-tools-0.1.0.zip",
"sha256": "834512494bbfba9918a9d8131efd512a09619a150823591e2d13ea385ced00e9",
"target": "epub"
},
{
"id": "de.add-ideas.archive-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/archive-tools/releases/download/v0.1.0/archive-tools-0.1.0.zip",
"sha256": "88a8efb39129bb813c97fb4d80257ee339bbfcec2a73b080a0a89dc76cdd2958",
"target": "archive"
},
{
"id": "de.add-ideas.privacy-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/privacy-tools/releases/download/v0.1.0/privacy-tools-0.1.0.zip",
"sha256": "0d6c071837b8ce705e456d44888378f3a7f9427a352f0bd4b60512f6c41465d4",
"target": "privacy"
},
{
"id": "de.add-ideas.crypto-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/crypto-tools/releases/download/v0.1.0/crypto-tools-0.1.0.zip",
"sha256": "bfced32f44918214ffd31c5d4730aee7bffd75e7952e9a6d16b6eb7eb68fed35",
"target": "crypto"
},
{
"id": "de.add-ideas.barcode-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/barcode-tools/releases/download/v0.1.0/barcode-tools-0.1.0.zip",
"sha256": "22cede58d279f15419b342862bf6545cace831d1e02c0634fbd01aeab3bd3e63",
"target": "barcode"
},
{
"id": "de.add-ideas.network-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/network-tools/releases/download/v0.1.0/network-tools-0.1.0.zip",
"sha256": "7e493a0aed643c712c38057bcd67c360bc6712d5d31ea82c222bf780464ff4a1",
"target": "network"
},
{
"id": "de.add-ideas.geo-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/geo-tools/releases/download/v0.1.0/geo-tools-0.1.0.zip",
"sha256": "88a46a56f3d3b5b61dc9bbb8795764b59aae1635da95120a0e499e33ef652e8f",
"target": "geo"
},
{
"id": "de.add-ideas.helper-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/helper-tools/releases/download/v0.1.0/helper-tools-0.1.0.zip",
"sha256": "bcdbd2ffc721ed1a2e9432eea1f90d7b4526d86934c3b5de6f522fd8bd58fd77",
"target": "helper"
},
{
"id": "de.add-ideas.rand-tools",
"version": "0.1.1",
"artifact": "https://git.add-ideas.de/lotobo/rand-tools/releases/download/v0.1.1/rand-tools-0.1.1.zip",
"sha256": "02dffcbbf1c3ff65236a83466aa750c3848777e4a69ac389fe24da02abfc0e77",
"target": "rand"
},
{
"id": "de.add-ideas.data-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/data-tools/releases/download/v0.1.0/data-tools-0.1.0.zip",
"sha256": "83ab02c9827d122c83b05c230e62c0ee87b330604acfff4990c58310f7956a1f",
"target": "data"
},
{
"id": "de.add-ideas.diff-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/diff-tools/releases/download/v0.1.0/diff-tools-0.1.0.zip",
"sha256": "023311343152aac11bfc00d58029b24ef0efe5ee4113aeb2a9d000ebe2460d72",
"target": "diff"
},
{
"id": "de.add-ideas.time-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/time-tools/releases/download/v0.1.0/time-tools-0.1.0.zip",
"sha256": "9a5545a3e684a207d7b2d6663d42a117cb5bb3303f35dc889a2651b67bfcf08f",
"target": "time"
},
{
"id": "de.add-ideas.text-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/text-tools/releases/download/v0.1.0/text-tools-0.1.0.zip",
"sha256": "242eb15005a18e0f13ba03544c633834416707e2629585868bfcd6f0c1cc5aec",
"target": "text"
},
{
"id": "de.add-ideas.unicode-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/unicode-tools/releases/download/v0.1.0/unicode-tools-0.1.0.zip",
"sha256": "1cf557d3ace9a41c7fa72cb5c1b149e669203a682174939f2e3aa376e1c6f22a",
"target": "unicode"
},
{
"id": "de.add-ideas.flow-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/flow-tools/releases/download/v0.1.0/flow-tools-0.1.0.zip",
"sha256": "abc8c50c95509484afa27606e6dc88087409fd0a8609fea6e99915cac703d2d5",
"target": "flow"
},
{
"id": "de.add-ideas.subtitle-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/subtitle-tools/releases/download/v0.1.0/subtitle-tools-0.1.0.zip",
"sha256": "be251beb06fe62da6b2dde79799e48d28148dc81cba84998ba51ced328509fc6",
"target": "subtitle"
},
{
"id": "de.add-ideas.midi-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/midi-tools/releases/download/v0.1.0/midi-tools-0.1.0.zip",
"sha256": "5f55fe448720d989aaf93cd25c18644b99df97bd3a32b297e1dc6f3d04777536",
"target": "midi"
},
{
"id": "de.add-ideas.3d-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/3d-tools/releases/download/v0.1.0/3d-tools-0.1.0.zip",
"sha256": "63d7c028e5fb8e0644855720d2088a23623b73f9e7f656485c1340b6e51dca1a",
"target": "3d"
},
{
"id": "de.add-ideas.query-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/query-tools/releases/download/v0.1.0/query-tools-0.1.0.zip",
"sha256": "c28fa57a266f32339f5f83c1082920ce3d601167c86a40516fe2e33d867545d6",
"target": "query"
},
{
"id": "de.add-ideas.scan-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/scan-tools/releases/download/v0.1.0/scan-tools-0.1.0.zip",
"sha256": "f741257053355ed0e2c46261d650c1bfdd70de9cc4355af526fb65bedf6a6096",
"target": "scan"
},
{
"id": "de.add-ideas.package-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/package-tools/releases/download/v0.1.0/package-tools-0.1.0.zip",
"sha256": "bbbba42319f77fc85ca38a87bef2317f8500326c9c781462561abafa37de2c97",
"target": "package"
},
{
"id": "de.add-ideas.label-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/label-tools/releases/download/v0.1.0/label-tools-0.1.0.zip",
"sha256": "0e658518da0eb9df204cc19bf07ef84e5e84c38d62604403a23e76938ecc8dd1",
"target": "label"
},
{
"id": "de.add-ideas.font-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/font-tools/releases/download/v0.1.0/font-tools-0.1.0.zip",
"sha256": "ee0b51e2ec63f38ae5fd2e9be8968f58f27e8cc243c429a3fc057e8cbfc3b582",
"target": "font"
},
{
"id": "de.add-ideas.fixture-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/fixture-tools/releases/download/v0.1.0/fixture-tools-0.1.0.zip",
"sha256": "9d41d63d33430bd8390ca9ddacdc14062205640a7ff8ed259192af943b430541",
"target": "fixture"
},
{
"id": "de.add-ideas.minimize-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/minimize-tools/releases/download/v0.1.0/minimize-tools-0.1.0.zip",
"sha256": "2e67cfdd8d0d4569729279da834b8c5bfa8ddd659068cfd7013a96f0031ecc05",
"target": "minimize"
},
{
"id": "de.add-ideas.format-lab",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/format-lab/releases/download/v0.1.0/format-lab-0.1.0.zip",
"sha256": "3fc0037bcdc4c7e58cc7de4a09a69c775ecc2605e820c3cdb5106cbc87de008c",
"target": "format-lab"
},
{
"id": "de.add-ideas.repro-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/repro-tools/releases/download/v0.1.0/repro-tools-0.1.0.zip",
"sha256": "c5c0dc7874bdeb241894d2475f2fde313e93231f3513205c5122336548c9c758",
"target": "repro"
},
{
"id": "de.add-ideas.schema-tools",
"version": "0.1.2",
"artifact": "https://git.add-ideas.de/lotobo/schema-tools/releases/download/v0.1.2/schema-tools-0.1.2.zip",
"sha256": "038f369ca19601a1a497d5435f3cee596946f93216cd796864d3e04a8d7bf3c7",
"target": "schema"
},
{
"id": "de.add-ideas.log-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/log-tools/releases/download/v0.1.0/log-tools-0.1.0.zip",
"sha256": "f16829d6e0a00981c92fa8704897da9aaeb4fcfc9af4ad8e45165e9dd35c2fdd",
"target": "log"
},
{
"id": "de.add-ideas.binary-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/binary-tools/releases/download/v0.1.0/binary-tools-0.1.0.zip",
"sha256": "6a9fdfa6ca87617151a49f9efde4edaca62d547756ed98459b1b355a7d05ac9d",
"target": "binary"
},
{
"id": "de.add-ideas.git-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/git-tools/releases/download/v0.1.0/git-tools-0.1.0.zip",
"sha256": "b71026de7feac68a4b2b66c40dd4b9c79201549a07cb204640e6923cf2a93678",
"target": "git"
},
{
"id": "de.add-ideas.api-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/api-tools/releases/download/v0.1.0/api-tools-0.1.0.zip",
"sha256": "fa544b99b1bf3e92beb95f77fadfaceb55fbadaf35dc3290603b110e6fb965e5",
"target": "api"
},
{
"id": "de.add-ideas.mail-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/mail-tools/releases/download/v0.1.0/mail-tools-0.1.0.zip",
"sha256": "81cf378ef7c63969fc2f13a872ff6b97313f13124623f457461b69111a1f3d12",
"target": "mail"
},
{
"id": "de.add-ideas.calendar-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/calendar-tools/releases/download/v0.1.0/calendar-tools-0.1.0.zip",
"sha256": "f37871322b60d3ef522350634360b8ec5304ecb63ebd342bec2145a29156d8cc",
"target": "calendar"
},
{
"id": "de.add-ideas.contact-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/contact-tools/releases/download/v0.1.0/contact-tools-0.1.0.zip",
"sha256": "7afa6daedabd9553c01c03b735cfc95265cfc862094d82e3e65a840a4c0ed1d2",
"target": "contact"
},
{
"id": "de.add-ideas.diagram-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/diagram-tools/releases/download/v0.1.0/diagram-tools-0.1.0.zip",
"sha256": "c19313d3a5ef1461bcbe719591cc0f5b27069bd2294f11a4b14c075cfd703929",
"target": "diagram"
},
{
"id": "de.add-ideas.token-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/token-tools/releases/download/v0.1.0/token-tools-0.1.0.zip",
"sha256": "c3800519f023b40868849a83fbe2631fd78be1b47884f85aee3de98fc72f884f",
"target": "token"
},
{
"id": "de.add-ideas.device-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/device-tools/releases/download/v0.1.0/device-tools-0.1.0.zip",
"sha256": "6d5c587ee991efb291633f12e5e626a1580d18afcee1d1f296451f6fc2c60feb",
"target": "device"
}
]
}
+299 -5
View File
@@ -1,8 +1,8 @@
{
"$schema": "./toolbox-release-lock.schema.json",
"schemaVersion": 1,
"releaseVersion": "0.16.0",
"portalVersion": "0.2.18",
"releaseVersion": "0.19.0",
"portalVersion": "0.2.22",
"catalogue": {
"id": "de.add-ideas.toolbox",
"name": "add·ideas Toolbox",
@@ -57,9 +57,9 @@
},
{
"id": "de.add-ideas.auth-tools",
"version": "0.3.0",
"artifact": "https://git.add-ideas.de/lotobo/auth-tools/releases/download/v0.3.0/auth-tools-0.3.0.zip",
"sha256": "ac80a711a0fc00d554505e6278aa3557eca4248b6da2ac9e2bae74bc0b26e58e",
"version": "0.3.1",
"artifact": "https://git.add-ideas.de/lotobo/auth-tools/releases/download/v0.3.1/auth-tools-0.3.1.zip",
"sha256": "60e90492fb50d2ce23298b3a3af84b1e3be02bbf5dea01d478f889d65eb66f3a",
"target": "auth"
},
{
@@ -68,6 +68,300 @@
"artifact": "https://git.add-ideas.de/lotobo/sudoku-tools/releases/download/v0.2.1/sudoku-tools-0.2.1.zip",
"sha256": "3987813a3bcd24056b9ca9607ba5d74a094d54c15b0e8a7966df7373e87df67a",
"target": "sudoku"
},
{
"id": "de.add-ideas.colour-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/colour-tools/releases/download/v0.1.0/colour-tools-0.1.0.zip",
"sha256": "c933f506362709a031a5cd830657604510b8e4ccb1800be77d40d0eee256490b",
"target": "colour"
},
{
"id": "de.add-ideas.office-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/office-tools/releases/download/v0.1.0/office-tools-0.1.0.zip",
"sha256": "3f950a413c74bae3b8f190954272fd91c9b141aab4fa50c936d5ad3741539aaf",
"target": "office"
},
{
"id": "de.add-ideas.image-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/image-tools/releases/download/v0.1.0/image-tools-0.1.0.zip",
"sha256": "8aa67d0c3cfd1060c261e9be108fb443384aaec95f82d3c1b96b63b2d07963e1",
"target": "image"
},
{
"id": "de.add-ideas.file-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/file-tools/releases/download/v0.1.0/file-tools-0.1.0.zip",
"sha256": "9225ff60c639d563bb514ac390b5b2cbad4b8030a070e6398e7c200763c5f89e",
"target": "file"
},
{
"id": "de.add-ideas.epub-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/epub-tools/releases/download/v0.1.0/epub-tools-0.1.0.zip",
"sha256": "834512494bbfba9918a9d8131efd512a09619a150823591e2d13ea385ced00e9",
"target": "epub"
},
{
"id": "de.add-ideas.archive-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/archive-tools/releases/download/v0.1.0/archive-tools-0.1.0.zip",
"sha256": "88a8efb39129bb813c97fb4d80257ee339bbfcec2a73b080a0a89dc76cdd2958",
"target": "archive"
},
{
"id": "de.add-ideas.privacy-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/privacy-tools/releases/download/v0.1.0/privacy-tools-0.1.0.zip",
"sha256": "0d6c071837b8ce705e456d44888378f3a7f9427a352f0bd4b60512f6c41465d4",
"target": "privacy"
},
{
"id": "de.add-ideas.crypto-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/crypto-tools/releases/download/v0.1.0/crypto-tools-0.1.0.zip",
"sha256": "bfced32f44918214ffd31c5d4730aee7bffd75e7952e9a6d16b6eb7eb68fed35",
"target": "crypto"
},
{
"id": "de.add-ideas.barcode-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/barcode-tools/releases/download/v0.1.0/barcode-tools-0.1.0.zip",
"sha256": "22cede58d279f15419b342862bf6545cace831d1e02c0634fbd01aeab3bd3e63",
"target": "barcode"
},
{
"id": "de.add-ideas.network-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/network-tools/releases/download/v0.1.0/network-tools-0.1.0.zip",
"sha256": "7e493a0aed643c712c38057bcd67c360bc6712d5d31ea82c222bf780464ff4a1",
"target": "network"
},
{
"id": "de.add-ideas.geo-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/geo-tools/releases/download/v0.1.0/geo-tools-0.1.0.zip",
"sha256": "88a46a56f3d3b5b61dc9bbb8795764b59aae1635da95120a0e499e33ef652e8f",
"target": "geo"
},
{
"id": "de.add-ideas.helper-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/helper-tools/releases/download/v0.1.0/helper-tools-0.1.0.zip",
"sha256": "bcdbd2ffc721ed1a2e9432eea1f90d7b4526d86934c3b5de6f522fd8bd58fd77",
"target": "helper"
},
{
"id": "de.add-ideas.rand-tools",
"version": "0.1.1",
"artifact": "https://git.add-ideas.de/lotobo/rand-tools/releases/download/v0.1.1/rand-tools-0.1.1.zip",
"sha256": "02dffcbbf1c3ff65236a83466aa750c3848777e4a69ac389fe24da02abfc0e77",
"target": "rand"
},
{
"id": "de.add-ideas.data-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/data-tools/releases/download/v0.1.0/data-tools-0.1.0.zip",
"sha256": "83ab02c9827d122c83b05c230e62c0ee87b330604acfff4990c58310f7956a1f",
"target": "data"
},
{
"id": "de.add-ideas.diff-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/diff-tools/releases/download/v0.1.0/diff-tools-0.1.0.zip",
"sha256": "023311343152aac11bfc00d58029b24ef0efe5ee4113aeb2a9d000ebe2460d72",
"target": "diff"
},
{
"id": "de.add-ideas.time-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/time-tools/releases/download/v0.1.0/time-tools-0.1.0.zip",
"sha256": "9a5545a3e684a207d7b2d6663d42a117cb5bb3303f35dc889a2651b67bfcf08f",
"target": "time"
},
{
"id": "de.add-ideas.text-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/text-tools/releases/download/v0.1.0/text-tools-0.1.0.zip",
"sha256": "242eb15005a18e0f13ba03544c633834416707e2629585868bfcd6f0c1cc5aec",
"target": "text"
},
{
"id": "de.add-ideas.unicode-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/unicode-tools/releases/download/v0.1.0/unicode-tools-0.1.0.zip",
"sha256": "1cf557d3ace9a41c7fa72cb5c1b149e669203a682174939f2e3aa376e1c6f22a",
"target": "unicode"
},
{
"id": "de.add-ideas.flow-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/flow-tools/releases/download/v0.1.0/flow-tools-0.1.0.zip",
"sha256": "abc8c50c95509484afa27606e6dc88087409fd0a8609fea6e99915cac703d2d5",
"target": "flow"
},
{
"id": "de.add-ideas.subtitle-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/subtitle-tools/releases/download/v0.1.0/subtitle-tools-0.1.0.zip",
"sha256": "be251beb06fe62da6b2dde79799e48d28148dc81cba84998ba51ced328509fc6",
"target": "subtitle"
},
{
"id": "de.add-ideas.midi-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/midi-tools/releases/download/v0.1.0/midi-tools-0.1.0.zip",
"sha256": "5f55fe448720d989aaf93cd25c18644b99df97bd3a32b297e1dc6f3d04777536",
"target": "midi"
},
{
"id": "de.add-ideas.3d-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/3d-tools/releases/download/v0.1.0/3d-tools-0.1.0.zip",
"sha256": "63d7c028e5fb8e0644855720d2088a23623b73f9e7f656485c1340b6e51dca1a",
"target": "3d"
},
{
"id": "de.add-ideas.query-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/query-tools/releases/download/v0.1.0/query-tools-0.1.0.zip",
"sha256": "c28fa57a266f32339f5f83c1082920ce3d601167c86a40516fe2e33d867545d6",
"target": "query"
},
{
"id": "de.add-ideas.scan-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/scan-tools/releases/download/v0.1.0/scan-tools-0.1.0.zip",
"sha256": "f741257053355ed0e2c46261d650c1bfdd70de9cc4355af526fb65bedf6a6096",
"target": "scan"
},
{
"id": "de.add-ideas.package-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/package-tools/releases/download/v0.1.0/package-tools-0.1.0.zip",
"sha256": "bbbba42319f77fc85ca38a87bef2317f8500326c9c781462561abafa37de2c97",
"target": "package"
},
{
"id": "de.add-ideas.label-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/label-tools/releases/download/v0.1.0/label-tools-0.1.0.zip",
"sha256": "0e658518da0eb9df204cc19bf07ef84e5e84c38d62604403a23e76938ecc8dd1",
"target": "label"
},
{
"id": "de.add-ideas.font-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/font-tools/releases/download/v0.1.0/font-tools-0.1.0.zip",
"sha256": "ee0b51e2ec63f38ae5fd2e9be8968f58f27e8cc243c429a3fc057e8cbfc3b582",
"target": "font"
},
{
"id": "de.add-ideas.fixture-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/fixture-tools/releases/download/v0.1.0/fixture-tools-0.1.0.zip",
"sha256": "9d41d63d33430bd8390ca9ddacdc14062205640a7ff8ed259192af943b430541",
"target": "fixture"
},
{
"id": "de.add-ideas.minimize-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/minimize-tools/releases/download/v0.1.0/minimize-tools-0.1.0.zip",
"sha256": "2e67cfdd8d0d4569729279da834b8c5bfa8ddd659068cfd7013a96f0031ecc05",
"target": "minimize"
},
{
"id": "de.add-ideas.format-lab",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/format-lab/releases/download/v0.1.0/format-lab-0.1.0.zip",
"sha256": "3fc0037bcdc4c7e58cc7de4a09a69c775ecc2605e820c3cdb5106cbc87de008c",
"target": "format-lab"
},
{
"id": "de.add-ideas.repro-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/repro-tools/releases/download/v0.1.0/repro-tools-0.1.0.zip",
"sha256": "c5c0dc7874bdeb241894d2475f2fde313e93231f3513205c5122336548c9c758",
"target": "repro"
},
{
"id": "de.add-ideas.schema-tools",
"version": "0.1.2",
"artifact": "https://git.add-ideas.de/lotobo/schema-tools/releases/download/v0.1.2/schema-tools-0.1.2.zip",
"sha256": "038f369ca19601a1a497d5435f3cee596946f93216cd796864d3e04a8d7bf3c7",
"target": "schema"
},
{
"id": "de.add-ideas.log-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/log-tools/releases/download/v0.1.0/log-tools-0.1.0.zip",
"sha256": "f16829d6e0a00981c92fa8704897da9aaeb4fcfc9af4ad8e45165e9dd35c2fdd",
"target": "log"
},
{
"id": "de.add-ideas.binary-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/binary-tools/releases/download/v0.1.0/binary-tools-0.1.0.zip",
"sha256": "6a9fdfa6ca87617151a49f9efde4edaca62d547756ed98459b1b355a7d05ac9d",
"target": "binary"
},
{
"id": "de.add-ideas.git-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/git-tools/releases/download/v0.1.0/git-tools-0.1.0.zip",
"sha256": "b71026de7feac68a4b2b66c40dd4b9c79201549a07cb204640e6923cf2a93678",
"target": "git"
},
{
"id": "de.add-ideas.api-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/api-tools/releases/download/v0.1.0/api-tools-0.1.0.zip",
"sha256": "fa544b99b1bf3e92beb95f77fadfaceb55fbadaf35dc3290603b110e6fb965e5",
"target": "api"
},
{
"id": "de.add-ideas.mail-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/mail-tools/releases/download/v0.1.0/mail-tools-0.1.0.zip",
"sha256": "81cf378ef7c63969fc2f13a872ff6b97313f13124623f457461b69111a1f3d12",
"target": "mail"
},
{
"id": "de.add-ideas.calendar-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/calendar-tools/releases/download/v0.1.0/calendar-tools-0.1.0.zip",
"sha256": "f37871322b60d3ef522350634360b8ec5304ecb63ebd342bec2145a29156d8cc",
"target": "calendar"
},
{
"id": "de.add-ideas.contact-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/contact-tools/releases/download/v0.1.0/contact-tools-0.1.0.zip",
"sha256": "7afa6daedabd9553c01c03b735cfc95265cfc862094d82e3e65a840a4c0ed1d2",
"target": "contact"
},
{
"id": "de.add-ideas.diagram-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/diagram-tools/releases/download/v0.1.0/diagram-tools-0.1.0.zip",
"sha256": "c19313d3a5ef1461bcbe719591cc0f5b27069bd2294f11a4b14c075cfd703929",
"target": "diagram"
},
{
"id": "de.add-ideas.token-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/token-tools/releases/download/v0.1.0/token-tools-0.1.0.zip",
"sha256": "c3800519f023b40868849a83fbe2631fd78be1b47884f85aee3de98fc72f884f",
"target": "token"
},
{
"id": "de.add-ideas.device-tools",
"version": "0.1.0",
"artifact": "https://git.add-ideas.de/lotobo/device-tools/releases/download/v0.1.0/device-tools-0.1.0.zip",
"sha256": "6d5c587ee991efb291633f12e5e626a1580d18afcee1d1f296451f6fc2c60feb",
"target": "device"
}
]
}
+2 -2
View File
@@ -83,7 +83,7 @@ function makeLock(artifact: string, sha256: string) {
return {
schemaVersion: 1,
releaseVersion: '0.1.0',
portalVersion: '0.2.18',
portalVersion: '0.2.22',
catalogue: {
id: 'de.add-ideas.toolbox',
name: 'Test Toolbox',
@@ -290,7 +290,7 @@ describe('release assembly integrity', () => {
expect(await sha256File(utcArchive)).toBe(
await sha256File(honoluluArchive)
);
});
}, 30_000);
it('rejects a valid archive whose manifest identity is not the lock identity', async () => {
const directory = await temporaryDirectory();
+103 -14
View File
@@ -22,7 +22,63 @@ const nginxConfig = readFileSync(
);
const releaseLock = JSON.parse(
readFileSync(path.join(projectRoot, 'release', 'toolbox.lock.json'), 'utf8')
) as { releaseVersion: string };
) as { releaseVersion: string; apps: Array<{ target: string }> };
const developmentCatalogue = JSON.parse(
readFileSync(path.join(projectRoot, 'public', 'toolbox.catalog.json'), 'utf8')
) as { apps: Array<{ manifest: string; enabled: boolean }> };
const expectedAppTargets = [
'pdf',
'xslt',
'onenote',
'av',
'regex',
'svg',
'auth',
'sudoku',
'colour',
'office',
'image',
'file',
'epub',
'archive',
'privacy',
'crypto',
'barcode',
'network',
'geo',
'helper',
'rand',
'data',
'diff',
'time',
'text',
'unicode',
'flow',
'subtitle',
'midi',
'3d',
'query',
'scan',
'package',
'label',
'font',
'fixture',
'minimize',
'format-lab',
'repro',
'schema',
'log',
'binary',
'git',
'api',
'mail',
'calendar',
'contact',
'diagram',
'token',
'device',
] as const;
const immutableCacheControl = 'public, max-age=31536000, immutable';
const immutableUriPatterns = Array.from(
@@ -85,16 +141,7 @@ describe('production deployment', () => {
expect(containerfile).toContain(
'COPY --from=release --chown=101:101 /tmp/toolbox/'
);
for (const app of [
'pdf',
'xslt',
'onenote',
'av',
'regex',
'svg',
'auth',
'sudoku',
]) {
for (const app of expectedAppTargets) {
expect(containerfile).toContain(
`test -f /tmp/toolbox/apps/${app}/toolbox-app.json`
);
@@ -102,6 +149,18 @@ describe('production deployment', () => {
expect(containerfile).toMatch(/\nUSER 101:101\nEXPOSE 8080\n/u);
});
it('keeps the development catalogue aligned with all release targets', () => {
expect(releaseLock.apps.map(({ target }) => target)).toEqual(
expectedAppTargets
);
expect(developmentCatalogue.apps).toEqual(
expectedAppTargets.map((target) => ({
manifest: `./apps/${target}/toolbox-app.json`,
enabled: true,
}))
);
});
it('uses only the requested external Traefik network and redirects HTTP to HTTPS', () => {
expect(compose).toContain('dockerfile: Containerfile.release');
expect(compose).toContain('traefik.enable: "true"');
@@ -167,9 +226,21 @@ describe('production deployment', () => {
expect(compose).not.toContain('addideas-auth-stripprefix');
});
it('grants camera capture only to the isolated authentication hostname', () => {
expect(nginxConfig).toMatch(
/map \$host \$toolbox_permissions_policy\s*\{\s*default "camera=\(\), microphone=\(\), geolocation=\(\), payment=\(\), usb=\(\)";\s*"auth\.toolbox\.add-ideas\.de" "camera=\(self\), microphone=\(\), geolocation=\(\), payment=\(\), usb=\(\)";\s*\}/mu
it('scopes camera and device probes while denying sensitive features by default', () => {
expect(nginxConfig).toContain(
'default "camera=(), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";'
);
expect(nginxConfig).toContain(
'"~^auth\\.toolbox\\.add-ideas\\.de:" "camera=(self), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";'
);
expect(nginxConfig).toContain(
'"~^[^:]+:/apps/barcode(?:/|$)" "camera=(self), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";'
);
expect(nginxConfig).toContain(
'"~^[^:]+:/apps/scan(?:/|$)" "camera=(self), microphone=(), display-capture=(), geolocation=(), payment=(), usb=()";'
);
expect(nginxConfig).toContain(
'"~^[^:]+:/apps/device(?:/|$)" "camera=(self), microphone=(self), display-capture=(self), geolocation=(), payment=(), usb=()";'
);
expect(nginxConfig).toContain(
'add_header Permissions-Policy $toolbox_permissions_policy always;'
@@ -179,6 +250,14 @@ describe('production deployment', () => {
).toHaveLength(1);
});
it('keeps application network connections same-origin', () => {
expect(nginxConfig).toMatch(
/^\s*add_header Content-Security-Policy "[^"]*connect-src 'self';[^"]*" always;$/mu
);
expect(nginxConfig).not.toContain('$toolbox_connect_sources');
expect(nginxConfig).not.toMatch(/https?:\/\//u);
});
it('quotes nginx regular expressions that contain brace quantifiers', () => {
expect(nginxConfig).toContain(
'"~^/(?:.*/)?assets/.*-[A-Za-z0-9_-]{8,}\\.[^/]+$"'
@@ -254,10 +333,20 @@ describe('production deployment', () => {
expect(staticLocationIndex).toBeGreaterThan(moduleLocationIndex);
});
it('serves bundled Scan OCR language data as gzip without widening the static route', () => {
const languageLocation =
/location ~\* \^\/apps\/scan\/ocr\/lang\/\[a-z0-9_-\]\+\\\.traineddata\\\.gz\$\s*\{\s*types\s*\{\s*application\/gzip gz;\s*\}\s*try_files \$uri =404;\s*\}/mu;
expect(nginxConfig).toMatch(languageLocation);
expect(nginxConfig).not.toMatch(
/location ~\* \\.\(\?:[^\n)]*\bgz\b[^\n)]*\)/u
);
});
it('allows same-origin WebAssembly workers and local blob media previews', () => {
expect(nginxConfig).toContain("script-src 'self' 'wasm-unsafe-eval'");
expect(nginxConfig).toContain("worker-src 'self' blob:");
expect(nginxConfig).toContain("media-src 'self' blob:");
expect(nginxConfig).toContain("font-src 'self' data: blob:");
expect(nginxConfig).not.toContain("'unsafe-eval'");
});
+22 -1
View File
@@ -48,6 +48,12 @@ describe('portal UI', () => {
expect(
screen.getByTestId('app-card-de.add-ideas.auth-tools')
).toHaveTextContent('OTP & Passkeys');
expect(
screen.getByTestId('app-card-de.add-ideas.colour-tools')
).toHaveTextContent('Colour');
expect(
screen.getByTestId('app-card-de.add-ideas.office-tools')
).toHaveTextContent('Office');
expect(
screen.queryByText(
'Page-level PDF operations performed locally in the browser.'
@@ -416,6 +422,8 @@ describe('portal UI', () => {
'de.add-ideas.svg-tools',
'de.add-ideas.auth-tools',
'de.add-ideas.sudoku-tools',
'de.add-ideas.colour-tools',
'de.add-ideas.office-tools',
],
hidden: [],
theme: 'light',
@@ -436,6 +444,8 @@ describe('portal UI', () => {
screen.getByTestId('app-card-de.add-ideas.svg-tools'),
screen.getByTestId('app-card-de.add-ideas.auth-tools'),
screen.getByTestId('app-card-de.add-ideas.sudoku-tools'),
screen.getByTestId('app-card-de.add-ideas.colour-tools'),
screen.getByTestId('app-card-de.add-ideas.office-tools'),
];
cards.forEach((card, index) => {
const rect = {
@@ -466,7 +476,16 @@ describe('portal UI', () => {
within(tools)
.getAllByRole('heading', { level: 3 })
.map((heading) => heading.textContent)
).toEqual(['XSLT', 'PDF', 'OneNote', 'SVG', 'OTP & Passkeys', 'Sudoku']);
).toEqual([
'XSLT',
'PDF',
'OneNote',
'SVG',
'OTP & Passkeys',
'Sudoku',
'Colour',
'Office',
]);
});
expect(
JSON.parse(localStorage.getItem(PREFERENCES_KEY) ?? '{}').order
@@ -477,6 +496,8 @@ describe('portal UI', () => {
'de.add-ideas.svg-tools',
'de.add-ideas.auth-tools',
'de.add-ideas.sudoku-tools',
'de.add-ideas.colour-tools',
'de.add-ideas.office-tools',
]);
});
+2 -2
View File
@@ -489,9 +489,9 @@ export default function App() {
</span>
</p>
<span>
Portal v0.2.18 ·{' '}
Portal v0.2.22 ·{' '}
<a
href="https://git.add-ideas.de/lotobo/toolbox-portal/src/tag/v0.16.0"
href="https://git.add-ideas.de/lotobo/toolbox-portal/src/tag/v0.19.0"
target="_blank"
rel="noopener noreferrer"
>
+3 -1
View File
@@ -10,7 +10,7 @@ describe('catalogue loading', () => {
const loaded = await loadCatalogue('/toolbox.catalog.json');
expect(loaded.catalogue.name).toBe('add·ideas Toolbox');
expect(loaded.homeUrl).toBe('http://localhost:3000/');
expect(loaded.apps).toHaveLength(6);
expect(loaded.apps).toHaveLength(8);
expect(loaded.apps[0]).toMatchObject({
id: 'de.add-ideas.pdf-tools',
name: 'PDF Workbench',
@@ -43,6 +43,8 @@ describe('catalogue loading', () => {
'de.add-ideas.svg-tools',
'de.add-ideas.auth-tools',
'de.add-ideas.sudoku-tools',
'de.add-ideas.colour-tools',
'de.add-ideas.office-tools',
]);
expect(loaded.unavailable).toHaveLength(1);
expect(loaded.unavailable[0]?.reason).toMatch(/HTTP 404/);
+76
View File
@@ -202,6 +202,76 @@ export const sudokuManifest: ToolboxAppManifest = {
],
};
export const colourManifest: ToolboxAppManifest = {
...sudokuManifest,
id: 'de.add-ideas.colour-tools',
name: 'Colour Tools',
version: '0.1.0',
description:
'Convert, composite, compare and build colours locally in the browser.',
categories: ['graphics', 'design', 'developer'],
tags: ['colour', 'rgba', 'oklch', 'palette', 'gradient', 'contrast'],
requirements: {
secureContext: false,
workers: true,
indexedDb: false,
crossOriginIsolated: false,
topLevelContext: false,
},
privacy: {
processing: 'local',
fileUploads: false,
telemetry: false,
label: 'Colours and images stay in this browser; nothing is uploaded.',
},
source: {
repository: 'https://git.add-ideas.de/lotobo/colour-tools',
license: 'GPL-3.0-or-later',
},
actions: [
{
id: 'source',
label: 'Source',
url: 'https://git.add-ideas.de/lotobo/colour-tools',
},
],
};
export const officeManifest: ToolboxAppManifest = {
...sudokuManifest,
id: 'de.add-ideas.office-tools',
name: 'Office Tools',
version: '0.1.0',
description:
'Open and inspect documents, spreadsheets and presentations locally in the browser.',
categories: ['documents', 'office', 'productivity'],
tags: ['document', 'spreadsheet', 'presentation', 'docx', 'xlsx', 'pptx'],
requirements: {
secureContext: false,
workers: true,
indexedDb: false,
crossOriginIsolated: false,
topLevelContext: false,
},
privacy: {
processing: 'local',
fileUploads: false,
telemetry: false,
label: 'Office files stay in this browser; nothing is uploaded.',
},
source: {
repository: 'https://git.add-ideas.de/lotobo/office-tools',
license: 'GPL-3.0-or-later',
},
actions: [
{
id: 'source',
label: 'Source',
url: 'https://git.add-ideas.de/lotobo/office-tools',
},
],
};
export const catalogue: ToolboxCatalog = {
schemaVersion: 1,
id: 'de.add-ideas.toolbox',
@@ -215,6 +285,8 @@ export const catalogue: ToolboxCatalog = {
{ manifest: './apps/svg/toolbox-app.json', enabled: true },
{ manifest: './apps/auth/toolbox-app.json', enabled: true },
{ manifest: './apps/sudoku/toolbox-app.json', enabled: true },
{ manifest: './apps/colour/toolbox-app.json', enabled: true },
{ manifest: './apps/office/toolbox-app.json', enabled: true },
],
};
@@ -242,6 +314,10 @@ export function catalogueFetch(overrides: Record<string, Response> = {}) {
return Response.json(authManifest);
if (url.pathname.endsWith('/apps/sudoku/toolbox-app.json'))
return Response.json(sudokuManifest);
if (url.pathname.endsWith('/apps/colour/toolbox-app.json'))
return Response.json(colourManifest);
if (url.pathname.endsWith('/apps/office/toolbox-app.json'))
return Response.json(officeManifest);
return new Response('Not found', { status: 404 });
};
}
+24
View File
@@ -63,4 +63,28 @@ describe('compact tool presentation', () => {
expect(shortToolTitle(sudoku)).toBe('Sudoku');
expect(shortToolDescription(sudoku)).toBe('Set, play and solve locally.');
});
it('uses the compact Colour tile copy', () => {
const colour = app(
'de.add-ideas.colour-tools',
'Colour Tools',
'Convert, composite, compare and build colours locally in the browser.'
);
expect(shortToolTitle(colour)).toBe('Colour');
expect(shortToolDescription(colour)).toBe(
'Convert and build colours locally.'
);
});
it('uses the compact Office tile copy', () => {
const office = app(
'de.add-ideas.office-tools',
'Office Tools',
'Open and inspect documents, spreadsheets and presentations locally in the browser.'
);
expect(shortToolTitle(office)).toBe('Office');
expect(shortToolDescription(office)).toBe('Open office files locally.');
});
});
+8
View File
@@ -33,6 +33,14 @@ const PRESENTATION: Record<string, { title: string; description: string }> = {
title: 'Sudoku',
description: 'Set, play and solve locally.',
},
'de.add-ideas.colour-tools': {
title: 'Colour',
description: 'Convert and build colours locally.',
},
'de.add-ideas.office-tools': {
title: 'Office',
description: 'Open office files locally.',
},
};
export function shortToolTitle(app: ResolvedApp): string {
+2
View File
@@ -10,5 +10,7 @@ export default defineConfig({
setupFiles: './src/test/setup.ts',
css: true,
restoreMocks: true,
pool: 'threads',
maxWorkers: 1,
},
});