Skip to content

fix(reliability): reject malformed autosave queue options before key enumeration #353

Description

@seonghobae

Buyer-visible autosave reliability boundary

Protected main@e8109ec2a17de8bd6594487aa12c8c8a93cb2c03 exposes framework-free createDocumentAutosaveQueue(options). Its exact-options validator currently calls Reflect.ownKeys(options) before inspecting the required fixed save descriptor. A malformed host result such as { save: 1 } wrapped by a Proxy can therefore execute a caller-controlled ownKeys trap (or materialize arbitrary key metadata) even though the required save field already proves the options can never be accepted.

The host owns persistence/transport; Inkspan owns deterministic validation of the callback configuration it retains. This is local validation/resource hardening only and adds no transport, persistence, authentication, authorization, tenancy, credentials, network, model/provider, migration, retention, deployment, or durable-audit authority.

Test-first acceptance

  1. Start from the independently resolved protected main generation and own only src/autosave/package.ts plus a dedicated autosave option-preflight regression. Freeze if another writer begins targeting either path.
  2. RED through public createDocumentAutosaveQueue(): provide a Proxy whose underlying own save data property is non-callable and whose ownKeys trap records/throws. Require the existing redacted invalid_options error and prove protected production invokes ownKeys before recognizing the invalid required capability.
  3. GREEN: inspect the required save own-property descriptor before global own-key enumeration. If it is absent, non-enumerable, accessor-backed, or non-callable, reject immediately without Reflect.ownKeys().
  4. Only after the required save capability is valid may exact-key-shape validation enumerate keys and validate optional onSnapshotChange. Preserve unknown-key/symbol/non-enumerable/accessor/reflection-failure rejection and do not invoke accessors.
  5. Preserve accepted queue behavior, callback receiver/value identity, detached evidence semantics, observer isolation, single-flight ordering, lifecycle snapshots, framework-free packaging, and stable payload-redacted errors.
  6. Maintain exact 100% owned-production statement/branch/function/line coverage plus package/browser/Office/Security Scan/SAST and applicable central required-workflow evidence on the final exact head.

Integration boundary

Keep this next-release repair Draft/unmerged while #118 owns the unchanged protected v0.6.0 publication/provenance source identity. Any head/live-base movement invalidates predecessor evidence; pending/queued/skipped/cancelled/absent/predecessor/status-only evidence is non-passing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions