release: prepare OneNote Tools 0.2.0
This commit is contained in:
@@ -1,20 +1,27 @@
|
||||
# Format support
|
||||
|
||||
## Version 0.1.0 support matrix
|
||||
## Version 0.2.0 support matrix
|
||||
|
||||
| Input or feature | Status | Tested evidence and boundary |
|
||||
| ---------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| Desktop revision-store `.one` | Supported subset | Real 34,904-byte Joplin golden; three pages |
|
||||
| FSSHTTPB-packaged `.one` | Supported subset | Licensed 17,197-byte Joplin golden; one page; unfragmented data elements |
|
||||
| Unknown/legacy `.one` variants | Unsupported | File type and format GUIDs are validated before traversal |
|
||||
| `.onepkg`, single CAB, LZX | Supported subset | Real Joplin package: LZX `0x1203`, three CFDATA blocks, seven entries, five sections, seven pages |
|
||||
| CAB LZX `0x1303` | Supported extraction | Byte-for-byte rust-cab MIT unit fixture, two text entries |
|
||||
| CAB without compression | Supported extraction | Byte-for-byte rust-cab MIT unit fixture |
|
||||
| CAB MSZIP | Supported extraction | rust-cab single-block fixture plus a generated two-block dictionary-chain fixture |
|
||||
| CAB Quantum | Supported extraction | Pinned compcol qtm.txt payload, generated one-folder CAB, and two-frame state/sentinel tests |
|
||||
| Multi-cabinet CAB / spanning files | Unsupported | Header flags and spanning folder indexes are rejected |
|
||||
| `.onetoc2` package entries | Listed only | Files are identified, but notebook hierarchy and section order are not interpreted |
|
||||
| Standalone `.onetoc2` | Unsupported in the app | The picker accepts only `.one` and `.onepkg` |
|
||||
| Input or feature | Status | Tested evidence and boundary |
|
||||
| -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| Desktop revision-store `.one` | Supported subset | Real 34,904-byte Joplin golden; three pages and rich content |
|
||||
| FSSHTTPB package-store `.one` | Supported subset | Licensed 17,197-byte Joplin golden; one page; unfragmented data elements |
|
||||
| Unknown/legacy `.one` variants | Unsupported | File type and format GUIDs are validated before traversal |
|
||||
| `.onepkg`, one CAB | Supported subset | Real Joplin LZX package; generated/pinned none, MSZIP, Quantum, and LZX codec fixtures |
|
||||
| `.onepkg`, complete CAB set | Supported extraction | Licensed five-part libmspack set plus split-block, spanning-file, ordering, and malformed-set tests |
|
||||
| Missing/inconsistent CAB parts | Rejected | Set ID, indexes, previous/next names, compression, split blocks, and spanning records must agree |
|
||||
| CAB without compression | Supported extraction | Byte-for-byte rust-cab fixture |
|
||||
| CAB MSZIP | Supported extraction | rust-cab single block plus generated two-block dictionary-chain fixture |
|
||||
| CAB Quantum | Supported extraction | Pinned compcol payloads and generated CAB integration fixture |
|
||||
| CAB LZX | Supported extraction | Real OneNote `0x1203` package and rust-cab `0x1303` fixture |
|
||||
| `.onetoc2` inside a package | Supported subset | Desktop golden/hierarchy tests; FSSHTTPB dispatch uses a mocked shared-store seam, not a real golden |
|
||||
| Standalone `.onetoc2` in the app | Not selectable | The picker accepts `.one`, or `.onepkg` together with `.cab` companions |
|
||||
| Rich text and layout hints | Supported subset | Run formatting, paragraph properties, safe links, and bounded layout metadata |
|
||||
| Tables | Supported subset | Rows, cells, nested blocks, column widths, locks, borders, and cell backgrounds |
|
||||
| Images | Supported subset | Lazy, signature/header-validated PNG and JPEG resources; unsafe images stay downloadable only |
|
||||
| Ink | Supported subset | Bounded delta decoding, strokes, colors, width/height, transparency, and SVG display/export |
|
||||
| Embedded attachments | Supported subset | `ATTACHMENT_DECLARATION`/file-data resources remain inert until explicit download |
|
||||
| Export | Supported subset | JSON, text, Markdown, inert HTML, and deterministic static notebook ZIP |
|
||||
|
||||
“Supported subset” is intentionally narrower than “all files with this
|
||||
extension.” A successful open requires the tested desktop or FSSHTTPB OneStore
|
||||
@@ -22,6 +29,8 @@ structures and content graph nodes. Malformed offsets, counts, references, CAB
|
||||
checksums, paths, compressed data, and unsupported variants produce bounded
|
||||
diagnostics or a controlled failure.
|
||||
|
||||
## OneStore and package boundaries
|
||||
|
||||
FSSHTTPB support covers the OneStore packaging envelope, Storage Index and
|
||||
Storage Manifest, header/data-root cells, bounded revision chains, Object Group
|
||||
partitions, resolved object/page-space references, and available Object Data
|
||||
@@ -31,49 +40,68 @@ the store adapter rejects packages containing fragment records with a
|
||||
controlled `UNSUPPORTED_FORMAT` error. Excluded object data cannot be
|
||||
reconstructed from a standalone file and is likewise unsupported.
|
||||
|
||||
For a split package, the browser must receive the `.onepkg` and every linked
|
||||
`.cab` companion in one selection. The extractor validates a complete,
|
||||
uniquely indexed cabinet chain before decoding. It reassembles split CFDATA
|
||||
blocks, preserves codec state across cabinets, and reconciles the CAB
|
||||
`continued from previous`, `continued to next`, and `continued both` file
|
||||
records. Partial sets are not opened heuristically.
|
||||
|
||||
The default LZX limit accepts CAB window sizes through 8 MiB, but compatibility
|
||||
claims are fixture-backed only for window bits 18 (`0x1203`) and 19 (`0x1303`).
|
||||
MSZIP validates the `CK` prefix, limits each compressed block to 32 KiB + 12,
|
||||
decodes into a fixed-size output buffer, requires the declared output length,
|
||||
and carries at most 32 KiB of history between blocks in one folder. The MSZIP
|
||||
tests establish CAB extraction behavior; no redistributable MSZIP-compressed
|
||||
OneNote export is currently present, so they do not establish producer-specific
|
||||
`.onepkg` compatibility.
|
||||
and carries at most 32 KiB of history between blocks in one logical folder.
|
||||
Quantum validates level/window metadata, bounds its window to 2 MiB by default,
|
||||
requires full 32 KiB intermediate frames, preserves its arithmetic models and
|
||||
LZ window across frames, and injects exactly one `0xFF` CAB block sentinel.
|
||||
Trailer padding is limited to the documented 0..4 zero bytes; match, frame,
|
||||
output, operation, and cancellation bounds are enforced. Its tests likewise
|
||||
establish CAB extraction behavior only: no redistributable Quantum-compressed
|
||||
OneNote export is currently present.
|
||||
LZ window across frames/cabinets, and injects exactly one `0xFF` CAB block
|
||||
sentinel. Trailer, match, frame, output, operation, and cancellation bounds are
|
||||
enforced.
|
||||
|
||||
Trailing CAB data is ignored with a warning. Reserved CAB areas are bounded and
|
||||
skipped. CAB names are decoded as strict UTF-8; unmarked valid UTF-8 receives a
|
||||
warning, while invalid non-ASCII legacy-code-page names are rejected rather
|
||||
than guessed.
|
||||
|
||||
## Extracted OneNote data
|
||||
## Notebook and page model
|
||||
|
||||
The supported section paths currently return:
|
||||
Supported `.onetoc2` stores provide authored section order, nested section
|
||||
groups, display names, identities, and colors. Exact normalized paths take
|
||||
precedence; same-directory file identity is a guarded fallback. Recycle-bin
|
||||
entries are omitted, duplicate/cyclic references are diagnosed, and readable
|
||||
sections not reachable from a TOC are appended deterministically. Page levels
|
||||
are interpreted as a page/subpage tree.
|
||||
|
||||
- section display name;
|
||||
- page ID, title, created/updated timestamp when available, and page level;
|
||||
- visible Unicode/extended-ASCII rich text as plain text and a text preview;
|
||||
- diagnostics tied to an offset, structure, or page where available.
|
||||
The supported section path returns:
|
||||
|
||||
It does not preserve visual position, rich-text formatting, list formatting,
|
||||
tables, images, ink, equations, embedded files, audio/video, active links,
|
||||
page versions/conflicts, or exports. Unsupported content objects remain visible
|
||||
as diagnostics instead of being silently presented as parsed.
|
||||
- section/page identities, names, timestamps, page levels, and diagnostics;
|
||||
- outlines and recursively nested content blocks;
|
||||
- rich-text runs with bold, italic, underline, strikeout, super/subscript,
|
||||
font, size, foreground/highlight color, paragraph alignment/spacing, and
|
||||
allow-listed `http`, `https`, and `mailto` links;
|
||||
- tables, lazy PNG/JPEG images, embedded-file declarations, and decoded ink;
|
||||
- bounded layout hints such as offsets, maximum dimensions, and alignment.
|
||||
|
||||
Within a supported `.onepkg`, each `.one` entry is parsed independently.
|
||||
Malformed or unsupported sections are marked failed/unsupported while other
|
||||
sections remain available. Package navigation is temporary normalized-path
|
||||
order until `.onetoc2` interpretation is implemented.
|
||||
This is not a pixel-perfect OneNote renderer. Equations, audio/video, page
|
||||
versions/conflicts, and producer-specific structures outside the golden corpus
|
||||
are not represented. Encountered unsupported object kinds remain visible as
|
||||
diagnostics. Active notebook HTML/SVG is never injected.
|
||||
|
||||
## Export
|
||||
|
||||
All exports are created inside the existing local parser worker. They include a
|
||||
versioned parser/support manifest, the readable page hierarchy, diagnostics,
|
||||
and unsupported-content summaries. The static ZIP contains inert semantic HTML
|
||||
plus JSON, text, Markdown, warnings, and bounded resources. Resource names are
|
||||
normalized, potentially active attachment suffixes are neutralized, and only
|
||||
validated image types may be embedded for automatic display.
|
||||
|
||||
Export is a representation of the parser-supported subset, not a round trip:
|
||||
it neither emits `.one`/`.onepkg` nor promises full OneNote visual fidelity.
|
||||
|
||||
## Test fixtures
|
||||
|
||||
The exact hashes, source revisions, licences, expected page names, and CAB
|
||||
The exact hashes, source revisions, licences, expected content, and CAB
|
||||
structures are recorded in
|
||||
[`tests/fixtures/README.md`](../tests/fixtures/README.md). Tests use no private
|
||||
notebooks and do not treat a synthetic archive as proof of Microsoft OneNote
|
||||
|
||||
@@ -3,32 +3,42 @@
|
||||
The desktop `.one` reader adapts selected structures from the pinned
|
||||
`onenote.rs` implementation. It is not a line-for-line or complete port.
|
||||
|
||||
| TypeScript module | Upstream path(s) | Revision | Port scope and deviations |
|
||||
| ---------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `src/onenote/onestore/file-node.ts` | `onestore/desktop/file_structure/file_node_list_fragment.rs`, `file_node/*`, chunk references | `onenote.rs@5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected; immutable byte input, strict range checks, fragment/child cycle detection, and depth/count limits |
|
||||
| `src/onenote/onestore/property-set.ts` | `onestore/shared/{object_prop_set,prop_set,property,object_stream_header}.rs` | same | Substantial; bounded vectors/counts/nesting and serializable discriminated unions |
|
||||
| `src/onenote/onestore/desktop-store.ts` | `onestore/desktop/{file_node,file_structure,objects}/*` | same | Selected desktop section path; explicit missing-reference errors; file-data/attachment payloads skipped with diagnostics |
|
||||
| `src/onenote/fsshttpb/*` | `fsshttpb/{data,data_element,packaging}.rs` | same | Native bounded package/header/data-element records, checked compact integers, zero-copy BLOB ranges; fragment records parsed but not assembled |
|
||||
| `src/onenote/onestore/fsshttp-store.ts` | `onestore/fsshttpb/{header,mapping_table,object,object_space,revision,revision_role}.rs` | same | Unfragmented package-store adapter; bounded/cycle-checked revision chains, newest-revision precedence, resolved positional reference arrays |
|
||||
| `src/onenote/one/{constants,section}.ts` | `one/property*`, `one/property_set/*`, `onenote/{section,page,page_series,outline,rich_text}.rs` | same | Page metadata, titles, and plain text only; bounded graph traversal; visual/embedded content diagnosed |
|
||||
| TypeScript module | Upstream path(s) | Revision | Port scope and deviations |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `src/onenote/onestore/file-node.ts` | `onestore/desktop/file_structure/file_node_list_fragment.rs`, `file_node/*`, chunk references | `onenote.rs@5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected; immutable byte input, strict range checks, fragment/child cycle detection, and depth/count limits |
|
||||
| `src/onenote/onestore/property-set.ts` | `onestore/shared/{object_prop_set,prop_set,property,object_stream_header}.rs` | same | Substantial; bounded vectors/counts/nesting and serializable discriminated unions |
|
||||
| `src/onenote/onestore/desktop-store.ts` | `onestore/desktop/{file_node,file_structure,objects}/*` | same | Selected desktop section/TOC paths; explicit missing-reference errors; bounded file-data references |
|
||||
| `src/onenote/onestore/file-data.ts` | `onestore/desktop/{file_node/shared,objects/file_data_store}.rs` | same | Bounded zero-copy file-data payload ranges, checked declarations, and explicit external/invalid availability |
|
||||
| `src/onenote/onestore/types.ts` | `onestore/desktop/common/*`, `onestore/shared/*`, and desktop object modules | same | Serializable structural records used across desktop and FSSHTTPB adapters |
|
||||
| `src/onenote/fsshttpb/*` | `fsshttpb/{data,data_element,packaging}.rs` | same | Native bounded package/header/data-element records, checked compact integers, zero-copy BLOB ranges; fragment records parsed but not assembled |
|
||||
| `src/onenote/onestore/fsshttp-store.ts` | `onestore/fsshttpb/{header,mapping_table,object,object_space,revision,revision_role}.rs` | same | Unfragmented package-store adapter; bounded/cycle-checked revision chains, newest-revision precedence, resolved positional reference arrays |
|
||||
| `src/onenote/one/{constants,section,content}.ts` | `one/property*`, `one/property_set/*`, `onenote/{section,page,page_series,outline,rich_text,table,image,embedded_file,ink}.rs` | same | Page metadata plus bounded recursive rich text, tables, resources, layout hints, and decoded ink in an inert browser DTO |
|
||||
| `src/onenote/one/property-access.ts` | `one/property/{simple,object_reference}.rs` | same | Typed property access and resolved/compact reference validation without coercion |
|
||||
| `src/onenote/one/section-content.ts` | `onenote/{section,page_series,page}.rs` | same | Worker-retained page/content/resource model with bounded diagnostics and timestamps |
|
||||
| `src/onenote/parser/parse-toc.ts` | `one/property_set/toc_container.rs` and desktop/FSSHTTP OneStore readers | same | Desktop/FSSHTTP TOC content, names, identities, ordering, colors, nesting, and bounded diagnostics |
|
||||
|
||||
The browser-native package path has separate MIT provenance:
|
||||
The browser-native package path has separate upstream provenance:
|
||||
|
||||
| TypeScript module | Upstream path(s) | Revision and selected licence | Port scope and deviations |
|
||||
| ------------------------------------------------------------------------ | ------------------------------------------------------ | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `src/onenote/onepkg/{cabinet,checksum}.ts` | rust-cab `src/{cabinet,folder,file,ctype,checksum}.rs` | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2`, MIT | CAB reading/checksum adapted for immutable browser bytes, strict normalized paths, checked ranges/checksums, whole-folder extraction, explicit limits, and cancellation/yield hooks; writers are not ported |
|
||||
| `src/onenote/onepkg/cabinet-set.ts` | libmspack `mspack/cabd.c` | `55d501976171397ccd5d5a7a1ca7da065b1d9a06`, LGPL-2.1-only | Complete named-set validation, split CFDATA reassembly, codec continuity, spanning-file reconciliation, aggregate limits, and immutable browser inputs |
|
||||
| `src/onenote/onepkg/mszip/decoder.ts` | rust-cab `src/mszip.rs`; fflate raw DEFLATE | rust-cab revision above; fflate 0.8.3, MIT | `CK` framing and persistent 32 KiB folder history follow rust-cab; raw DEFLATE uses fflate with a caller-owned bounded buffer and strict declared-size checks |
|
||||
| `src/onenote/onepkg/quantum/{bit-reader,budget,decoder,model,tables}.ts` | compcol `src/quantum/{bits,decoder,model,tables}.rs` | `04a6db2aa7bd487a89c559631d79d1b384139f50`, MIT | Native TypeScript arithmetic/model/LZ decoder; fixed CAB output, 2 MiB maximum window, strict match/frame/trailer checks, two-block lookahead, operation budget, and cancellation checkpoints |
|
||||
| `src/onenote/onepkg/lzx/{bit-reader,huffman,decoder}.ts` | lzxd 0.2.5 `src/{bitstream,tree,block,window,lib}.rs` | `4748e43594e3e30cff2ace3a6ad7a376c9816fdd`, MIT option of MIT OR Apache-2.0 | Directly translated core with typed arrays, CAB CFDATA boundaries, persistent folder state, strict malformed-stream errors, and operation/window/cancellation limits; delta reference data is omitted |
|
||||
|
||||
The bounded binary readers, format detection, parser limits/error model, path
|
||||
policy, worker protocol/DTOs, package-to-section boundary, and application UI
|
||||
are original TypeScript implementations guided by the normative specifications
|
||||
and project requirements.
|
||||
policy, package TOC-to-section hierarchy, worker protocol/DTOs, safe image
|
||||
inspection, export serializers/ZIP writer, and React application UI are original
|
||||
TypeScript implementations guided by the normative specifications and project
|
||||
requirements. The pinned `one2html` renderer informed expected visual semantics
|
||||
for rich text, tables, images, attachments, and ink; its Rust/templates/CSS were
|
||||
not copied or shipped.
|
||||
|
||||
Files adapted from `onenote.rs` carry an MPL-2.0 notice, SPDX identifier,
|
||||
upstream path/revision, and deviations. Files adapted from rust-cab, compcol,
|
||||
or lzxd carry their MIT provenance, copyright notice, exact revision, and deviations.
|
||||
or lzxd carry their MIT provenance, copyright notice, exact revision, and
|
||||
deviations. The multi-cabinet module carries libmspack's LGPL-2.1-only notice.
|
||||
Licence texts are reproduced in `LICENSES/` and included in the release ZIP.
|
||||
|
||||
Focused tests cover successful pinned fixtures plus malformed bounds,
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
# Specifications and pinned references
|
||||
|
||||
Version 0.1.0 records these immutable implementation revisions:
|
||||
Version 0.2.0 records these immutable implementation revisions:
|
||||
|
||||
| Repository | Exact revision | Use |
|
||||
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- |
|
||||
| [`toolbox-sdk`](https://git.add-ideas.de/zemion/toolbox-sdk/src/commit/5e206baf42dfae5a00f2743fb2cc501bb12d9b7a) | `5e206baf42dfae5a00f2743fb2cc501bb12d9b7a` | App contract, React shell, manifest schema/testkit, and nested-path behavior |
|
||||
| [`toolbox-portal`](https://git.add-ideas.de/zemion/toolbox-portal/src/commit/5d2e466ad61e36a0e2be2a2d8459b1a127f53f11) | `5d2e466ad61e36a0e2be2a2d8459b1a127f53f11` | Reviewed ZIP shape, exact checksum lock, and independent-app assembly model |
|
||||
| [`onenote.rs`](https://github.com/msiemens/onenote.rs/tree/5138a39a3f4e72b840932f9872fecde52fa9da60) | `5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected desktop/FSSHTTPB OneStore and MS-ONE structures adapted into TypeScript |
|
||||
| [`rust-cab`](https://github.com/mdsteele/rust-cab/tree/c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2) | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2` | CAB structures, checksum, enumeration/extraction, MSZIP history, and unit fixtures |
|
||||
| [`compcol`](https://github.com/KarpelesLab/compcol/tree/04a6db2aa7bd487a89c559631d79d1b384139f50) | `04a6db2aa7bd487a89c559631d79d1b384139f50` | Quantum bit reader, arithmetic models, LZ window, CAB sentinel behavior, and tests |
|
||||
| [`lzxd` 0.2.5](https://github.com/Lonami/lzxd/tree/4748e43594e3e30cff2ace3a6ad7a376c9816fdd) | `4748e43594e3e30cff2ace3a6ad7a376c9816fdd` | LZX bitstream, Huffman, block/window, match, and E8 logic adapted into TypeScript |
|
||||
| Repository | Exact revision | Use |
|
||||
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| [`toolbox-sdk`](https://git.add-ideas.de/zemion/toolbox-sdk/src/commit/5e206baf42dfae5a00f2743fb2cc501bb12d9b7a) | `5e206baf42dfae5a00f2743fb2cc501bb12d9b7a` | App contract, React shell, manifest schema/testkit, and nested-path behavior |
|
||||
| [`toolbox-portal`](https://git.add-ideas.de/zemion/toolbox-portal/src/commit/d46f1b61fb85a18299b6b8af2148dcd991ef6b05) | `d46f1b61fb85a18299b6b8af2148dcd991ef6b05` | Reviewed ZIP shape, exact checksum lock, independent-app assembly, and nginx deployment model |
|
||||
| [`onenote.rs`](https://github.com/msiemens/onenote.rs/tree/5138a39a3f4e72b840932f9872fecde52fa9da60) | `5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected desktop/FSSHTTPB OneStore and MS-ONE structures adapted into TypeScript |
|
||||
| [`rust-cab`](https://github.com/mdsteele/rust-cab/tree/c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2) | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2` | CAB structures, checksum, enumeration/extraction, MSZIP history, and unit fixtures |
|
||||
| [`compcol`](https://github.com/KarpelesLab/compcol/tree/04a6db2aa7bd487a89c559631d79d1b384139f50) | `04a6db2aa7bd487a89c559631d79d1b384139f50` | Quantum bit reader, arithmetic models, LZ window, CAB sentinel behavior, and tests |
|
||||
| [`lzxd` 0.2.5](https://github.com/Lonami/lzxd/tree/4748e43594e3e30cff2ace3a6ad7a376c9816fdd) | `4748e43594e3e30cff2ace3a6ad7a376c9816fdd` | LZX bitstream, Huffman, block/window, match, and E8 logic adapted into TypeScript |
|
||||
| [`libmspack`](https://github.com/kyz/libmspack/tree/55d501976171397ccd5d5a7a1ca7da065b1d9a06) | `55d501976171397ccd5d5a7a1ca7da065b1d9a06` | Multi-cabinet chain, split CFDATA, spanning-file semantics, and licensed fixtures |
|
||||
| [`one2html`](https://github.com/msiemens/one2html/tree/59930ad309004030f812790c6749efe4265bb6bd) | `59930ad309004030f812790c6749efe4265bb6bd` | Behavioral reference for rich text, tables, images, attachments, ink, and HTML rendering |
|
||||
|
||||
The SDK and Portal revisions were inspected from the local repositories. The
|
||||
four parser references were cloned and reviewed at the hashes above; a branch
|
||||
The SDK and Portal revisions were inspected from the local repositories. Every
|
||||
parser/renderer reference was cloned and reviewed at the hash above; a branch
|
||||
name or package version alone is not used as provenance. Source-level mappings
|
||||
and behavioural deviations are in [PORTING.md](PORTING.md).
|
||||
|
||||
@@ -50,5 +52,6 @@ The Microsoft documents are linked rather than copied. Their published pages
|
||||
can change independently; the source references and golden bytes remain pinned
|
||||
for reproducibility.
|
||||
|
||||
`one2html` is deliberately not pinned or inspected because visual HTML
|
||||
rendering is outside this release.
|
||||
The `one2html` renderer is a behavioral reference only: no Rust, Askama
|
||||
template, stylesheet, or generated HTML is shipped or executed by this
|
||||
application.
|
||||
|
||||
219
docs/SECURITY.md
219
docs/SECURITY.md
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user