release: prepare OneNote Tools 0.2.0

This commit is contained in:
2026-07-22 20:17:09 +02:00
parent edb19bfcc8
commit 41cffdc5d9
19 changed files with 423 additions and 234 deletions

View File

@@ -2,119 +2,172 @@
## Trust boundary and local processing
Selected `.one` and `.onepkg` files are untrusted. The main thread checks the
source size, reads one file into an `ArrayBuffer`, transfers it to a dedicated
module worker, and receives serializable data-transfer objects. CAB entries are
extracted only into memory; archive paths are never written to the filesystem.
Selected `.one`, `.onepkg`, and companion `.cab` files are untrusted. The main
thread validates the selection and combined size, reads the files into
`ArrayBuffer`s, and transfers them to a dedicated module worker. CAB entries
are extracted only into memory; archive paths are never written to the
filesystem.
The worker is a fault-containment and responsiveness boundary, not a security
sandbox. A successful open keeps its worker session alive for page requests.
Clearing the file, choosing another file, or unmounting the app terminates that
worker; a failed open also terminates it. JavaScript garbage collection does
not promise immediate release or secure erasure.
sandbox. A successful open keeps its session alive for page/resource/export
requests. Clearing the file, choosing another file, or unmounting the app
terminates that worker; a failed open also terminates it. JavaScript garbage
collection does not promise immediate release or secure erasure.
The application does not:
- upload or transmit notebook bytes;
- use a backend, proxy, telemetry, analytics, remote fonts, or external content
fetching;
- use a notebook-processing application backend, upload proxy, telemetry,
analytics, remote fonts, or notebook-referenced external content fetching;
the optional same-origin Toolbox catalogue/manifest is application chrome
and receives no notebook data;
- persist source or derived content in LocalStorage, IndexedDB, Cache Storage,
cookies, or a service worker;
- execute notebook content or inject notebook HTML/SVG;
- use WebAssembly, a Rust runtime, or a native helper.
## Active default limits
## Active parser defaults
The main thread rejects a source larger than 512 MiB before reading it. The
OneStore section parsers then apply these independent defaults:
The main thread accepts one `.one`, or one `.onepkg` plus its `.cab`
companions. It permits at most 256 selected parts, 512 MiB per file, and 512 MiB
combined before reading.
| Resource | Default limit |
| ------------------------------------- | -------------------: |
| Section bytes | 512 MiB |
| File-node list fragments / nesting | 16,384 / 64 |
| File nodes | 1,000,000 |
| Objects | 500,000 |
| Properties per set / property nesting | 16,384 / 64 |
| Stream IDs | 1,000,000 |
| FSSHTTPB revision-chain entries | 16,384 |
| One property vector | 64 MiB |
| Object references | 1,000,000 |
| Content-graph depth | 256 |
| Pages per section | 100,000 |
| Diagnostics per section | 10,000 |
| Extracted text per section | 2,000,000 characters |
The OneStore parser applies these independent defaults per section/store:
The CAB/package path applies these defaults:
| Resource | Default limit |
| ------------------------------------------------ | -------------------------: |
| Section bytes | 512 MiB |
| Transaction fragments / entries | 16,384 / 1,000,000 |
| File-node list fragments / nesting | 16,384 / 64 |
| File nodes | 1,000,000 |
| Objects | 500,000 |
| Properties per set / property nesting | 16,384 / 64 |
| Stream IDs | 1,000,000 |
| FSSHTTPB revision-chain entries | 16,384 |
| One property vector | 64 MiB |
| Desktop object-reference vector | 1,000,000 per vector |
| FSSHTTPB ExGUID/CellID references | 1,000,000 aggregate |
| Nested PropertySets per ObjectPropSet | 1,000,000 aggregate |
| File-data objects / one payload / total payloads | 10,000 / 256 MiB / 512 MiB |
| Content-graph depth | 256 |
| Content blocks / text runs / table cells | 100,000 each |
| Decoded ink points | 100,000 |
| Pages | 10,000 |
| Diagnostics | 10,000 |
| Retained rich/extracted text | 2,000,000 UTF-16 units |
| Resource | Default limit |
| ------------------------------- | -------------: |
| Cabinet input | 512 MiB |
| Folders / files | 1,024 / 10,000 |
| CFDATA blocks | 131,072 |
| CAB name bytes | 255 |
| Path characters / path segments | 4,096 / 64 |
| One extracted file | 256 MiB |
| One folder output | 512 MiB |
| Total folder output | 512 MiB |
| Total extracted entry bytes | 512 MiB |
| Folder compression ratio | 200:1 |
| One MSZIP compressed block | 32 KiB + 12 B |
| Quantum window | 2 MiB |
| LZX window | 8 MiB |
| LZX/Quantum decode operations | 1,000,000,000 |
Images are automatically previewable only when a bounded PNG IHDR or JPEG
marker/SOF inspection succeeds. The compressed payload must be at most 32 MiB,
each dimension at most 16,384 pixels, and the image at most 67,108,864 pixels.
JPEG inspection reads at most 1 MiB of markers and 4,096 marker records. Images
outside those limits stay inert and are available only through an explicit
download action.
The CAB/package path applies these defaults across a complete cabinet set:
| Resource | Default limit |
| ------------------------------------------- | -----------------: |
| One cabinet / complete set input | 512 MiB / 512 MiB |
| Cabinet parts | 256 |
| Folder segments / files | 1,024 / 10,000 |
| CFDATA fragments | 131,072 |
| CAB name bytes | 255 |
| Path characters / path segments | 4,096 / 64 |
| TOC construction operations / diagnostics | 1,000,000 / 10,000 |
| One extracted file | 256 MiB |
| One logical folder output | 512 MiB |
| Total folder output / extracted entry bytes | 512 MiB / 512 MiB |
| Logical-folder compression ratio | 200:1 |
| One MSZIP compressed block | 32 KiB + 12 B |
| Quantum window | 2 MiB |
| LZX window | 8 MiB |
| LZX/Quantum decode operations | 1,000,000,000 |
A CFDATA block may declare at most 32 KiB of output. Counts and offsets use
checked arithmetic and bounded readers. The CAB parser verifies supplied block
checksums, rejects overlapping/out-of-range data, rejects absolute/traversal,
empty, control-character, and case-insensitive duplicate paths, and refuses
multi-cabinet/spanning entries.
checksums; rejects overlapping/out-of-range data, traversal/absolute/control or
case-insensitive duplicate paths; and validates a complete cabinet set before
decoding. Set IDs, indexes, links, compression, split blocks, and spanning-file
records must agree. Reserve areas are private to each cabinet/folder and are
validated locally rather than compared across parts.
MSZIP checks its `CK` framing and raw DEFLATE data, writes into a fixed caller
buffer with one overflow-detection byte, requires the exact declared output
size, and retains no more than 32 KiB of history. LZX checks its window, Huffman
trees, block sizes, match ranges, output size, and operation budget. CAB
Quantum limits its window, model scans, arithmetic renormalisation, matches,
frame/output boundaries, operation count, and trailer padding. It queues at
most the current and next compressed block so a synthetic `0xFF` sentinel can
be consumed without buffering a complete folder. CAB extraction checks
cancellation during Quantum work and yields between data blocks so the worker
can process termination. Desktop OneStore traversal checks fragment/reference
cycles, nesting, object/property/reference counts, and byte ranges. FSSHTTPB
parsing bounds every declared stream body and compact integer, rejects invalid
end markers and non-zero package tails, checks mapping/reference counts and
revision cycles, and retains BLOB payloads as bounded source ranges. Fragment
records are range-checked, but packages containing them are rejected because
MSZIP checks `CK` framing and raw DEFLATE data, writes into a fixed caller
buffer with overflow detection, requires the declared output size, and keeps at
most 32 KiB of logical-folder history. LZX and Quantum validate their windows,
trees/models, blocks/frames, matches, output, trailer, and operation budgets.
Codec state is preserved across continued cabinet segments. Extraction checks
cancellation between data blocks and periodically yields to the worker loop.
Desktop OneStore traversal checks fragment/reference cycles, nesting,
object/property/reference counts, and byte ranges. FSSHTTPB parsing bounds every
declared stream body and compact integer, rejects invalid end markers and
non-zero package tails, checks aggregate reference/mapping counts and revision
cycles, and retains BLOB payloads as bounded source ranges. Fragment records
are range-checked, but packages containing them are rejected because
fragmented-element reconstruction is not implemented.
## Rendering and links
## Display and export budgets
DTO strings are rendered as React text nodes. Notebook HTML, active SVG,
scripts, attachment payloads, and automatic external navigation are not
rendered. Link activation is not implemented. If links are added, they require
explicit user action, scheme validation, and safe navigation attributes.
Parser DTOs are projected through a smaller page-display budget before React
creates nodes: 5,000 blocks, depth 64, 10,000 text runs, 500,000 displayed text
units, 2,000 table rows, 5,000 table cells, 256 columns, 10,000 ink strokes,
50,000 ink points, and 4,096 characters per metadata label. Exceeding a display
budget produces an explicit truncation notice. Newlines remain inside text
nodes instead of multiplying DOM elements.
## Known gaps and roadmap
Navigation and inspectors separately expose at most 250 page links, 500
notebook nodes at depth 16, 200 package entries per page, and 100 diagnostics
per page. Titles, previews, package paths, diagnostic fields, and panel labels
are length-bounded; pagination/truncation remains explicit in the UI.
- There is no wall-clock deadline. Synchronous OneStore `.one` parsing cannot
observe cooperative cancellation until control returns; terminating the
worker is the current hard stop.
- The package flow holds the source, decompressed folder buffers, extracted
entry slices, and parsed DTOs in memory at overlapping times. The byte/count
limits bound these individually but do not guarantee a low peak heap.
- Section text/page/diagnostic limits apply per contained section rather than
once to the complete package.
Export planning independently permits at most 10,000 sections, 100,000 pages,
1,000,000 blocks, depth 256, 100,000 diagnostics, 8,000,000 text units, and
500,000 ink points. One resource and all resources are capped at 64 MiB; one
standalone output or all uncompressed static-ZIP members are capped at 128 MiB.
Planning accounts for metadata and projected UTF-8 output before serialization,
then verifies actual encoded/member sizes. Resource views remain zero-copy until
the bounded serializer needs bytes.
## Rendering, links, and downloads
DTO strings are rendered as React text nodes. Notebook HTML, scripts, active
SVG, and attachment payloads are never injected. Only parsed ink coordinates
generate application-owned SVG path attributes. Hyperlinks require an explicit
click, are limited to `http`, `https`, or `mailto`, and use
`rel="noopener noreferrer"`.
Automatic image requests carry a distinct preview intent. The worker rejects a
non-image, unapproved media type, unsafe dimensions, or oversized payload before
allocating/copying its bytes to the main thread. Approved image bytes may cross
for automatic preview; attachment bytes and rejected image bytes cross only
after the user presses a download button.
Static export HTML is inert, contains no script or external fetch, escapes all
text/attributes, embeds only images that pass the same inspector, and
neutralizes potentially active attachment suffixes. Exports represent the
supported reader model; they do not write OneNote files.
## Known gaps
- There is no wall-clock deadline. Synchronous OneStore graph parsing cannot
observe cancellation until control returns; terminating the worker is the
current hard stop.
- Package opening can hold source cabinets, decompressed logical folders,
extracted entry views, and parsed DTOs at overlapping times. Byte/count limits
bound them, but do not guarantee a low peak heap.
- Section content limits apply per contained section rather than once to the
complete `.onepkg`; cabinet/TOC limits are aggregate for the package set.
- CAB checksums detect accidental corruption but do not authenticate a package.
- Format coverage is narrow and has only the documented golden files. New
producer/version claims require licensed regression fixtures and malformed
- Format coverage is limited to the documented golden files and structures.
New producer/version claims require licensed regression fixtures and malformed
variants.
- The worker boundary reduces UI impact but is not a substitute for browser and
operating-system isolation. Open especially sensitive files in a dedicated
browser profile if that risk matters.
Planned hardening includes an elapsed-time budget, cancellation checkpoints in
desktop OneStore graph traversal, aggregate package DTO/text budgets, lower
peak-memory extraction, expanded malformed-input/fuzz corpora, and additional
licensed OneNote export fixtures.
Planned hardening includes elapsed-time budgets, more cancellation checkpoints,
lower-peak-memory extraction, expanded malformed-input/fuzz corpora, fragmented
FSSHTTP reconstruction, and additional licensed OneNote producer fixtures.
## Fixtures and vulnerability reporting