Skip to content

feat(hangul): import and edit HWP/HWPX documents #319

Description

@seonghobae

Current authoritative state

The HWP/HWPX feature is implemented on the existing canonical single-writer Draft PR #320 / branch feat/hwp-hwpx-authoring. Protected shipped truth remains exact main@3b38ead2d00f44eb578d0689087b9293b3dabe1e; current exact Draft head is 5ee6e4d0c3b2a804f39a8d186a8bdd7c2a38a782, with PR base metadata aligned to that protected tip. GitHub reports the Draft mechanically mergeable; mergeability is not authorization.

Inkspan owns the bounded deterministic HWP/HWPX byte/JSON bridge, local conversion rules, deterministic frozen capability metadata, payload-redacted diagnostics, resource validation, cleanup containment, and committed synthetic fixture contracts. The host injects and owns HangulDocumentEngine and retains filesystem/network/WASM initialization, transport, auth, tenancy, persistence, credentials, model policy, deployment and durable-audit authority. Standalone Inkspan requires no service, DB, credential, network or model.

Implemented active-PR contract

  • open HWP/HWPX through host-owned engine capability and project the supported structural subset into framework-neutral editor JSON;
  • export edited JSON as HWPX by default or legacy HWP explicitly;
  • preserve paragraphs, headings, alignment, bold/italic/strike, structural lists, block quotes, code blocks and basic table topology;
  • fail closed on unsupported structures rather than silently discarding them;
  • enforce source/output byte ceilings and genuine Uint8Array snapshots;
  • reject host structural metadata above 4,096 sections, 1,000,000 paragraphs per section, or 16,777,216 UTF-16 code units per paragraph before traversal, host indexing, selection, deletion, or paste mutation (fix(reliability): validate Hangul engine structural counts before traversal #367);
  • treat those values as Inkspan safety/resource ceilings, not HWP/HWPX format maxima;
  • contain hostile option access (fix(reliability): redact hostile Hangul option access failures #366) and cleanup failures (fix(reliability): contain Hangul engine cleanup failures #365) without reflecting unknown thrown values;
  • validate host-returned source format / selection HTML as strings before member access or coercion;
  • expose one frozen deterministic capabilities object instead of forcing hosts to infer support from failures;
  • verify synthetic known-document HWPX/HWP fixtures and semantic reopen/round-trip behavior without customer documents.

docs/HANGUL.md, ADR 0030, and src/hangul/documentationContract.test.ts on the active branch bind the finite traversal ceilings and authority boundary into both human-readable and machine-checkable contracts. Active-PR documentation is not protected-main shipped truth.

Test-first lineage

  • deterministic capability metadata RED 59740977d26beadb5ef61cdd83990749e0616b31 failed typecheck because the required capabilities surface did not exist; GREEN e389742f85a2916241198af4676510f431207cdb adds the frozen capability object;
  • cleanup RED 4481666a6bbddb467ac0d9318c45d3b37a411cad -> GREEN 521900fde4347bc8b9cb4b966d7f1a930e9c7155;
  • hostile-option RED 907b088a77a6c0324b2907cba13235da8d508e58 -> GREEN 0786240d8e30e66effd8326fad3d5d67af427f4d;
  • structural-metadata REDs 6610482f5c9456274befe43dfde024da6975220d, c5615c9b28b741343fc234599a662eb117e50e7b, and f99891581dcdaae37bd8ccbf5136785f461af086 establish malformed host metadata rejection and stable traversal bounds;
  • resource-bound RED 030512a5496c8fa869fc0cb1c79724334d6919b1, exact-checkout CI 32394561877, build/test job 96508269729, typechecked and then exhausted the Node/Vitest heap near 4 GiB while exercising forged enormous metadata. That non-passing run proves safe-integer validation alone did not bound work;
  • narrow source repair 88936bd85345ec81daba1eaa497ed21418ce6dab applies the finite section/paragraph/paragraph-length ceilings before child traversal or host mutation;
  • dcefbe6d40bacc66e2b04dc85b68a04dca37d013, 487e6cb172454e6c0d90a7ecce3838ec068eefc3, and current 5ee6e4d0c3b2a804f39a8d186a8bdd7c2a38a782 converge executable documentation, docs/HANGUL.md, and ADR 0030 on those exact ceilings;
  • non-string engine-text RED 642ec3c1aef0d9b12441909ef253658c9526fecd -> GREEN 7c79ade8e6f00d47fcd2039412aebda67a01d364 (replayed on the synchronized branch as 38e0ff0);
  • committed known-document fixtures remain fail-closed and semantically reopenable on the current branch.

Exact-current-head evidence

For unchanged head 5ee6e4d0c3b2a804f39a8d186a8bdd7c2a38a782 against protected base 3b38ead2d00f44eb578d0689087b9293b3dabe1e at the latest fresh refetch:

  • CI 32395091285: completed / success;
  • build-and-test 96510085342: exact-current-head checkout, 161 test files / 898 tests, 100% statements / branches / functions / lines, packed-package verification, library build and demo build all successful;
  • Office Python 3.11-3.14 jobs: completed / success with dependency, coverage, docstring, wheel, schema and license gates;
  • Cross-engine Clipboard / Playwright job: completed / success;
  • Security Scan 32395091192: completed / success;
  • SAST Semgrep 32395091052: completed / success;
  • qualifying approving latest-push review remains absent.

All observed repository-owned exact-head workflows are terminal success; the absent qualifying latest-push approval remains non-passing. Predecessor evidence does not transfer. Any head/base movement invalidates this exact-current classification.

Integration boundary

The feature is active-PR truth only and is not protected-main shipped behavior. Keep #320 Draft/unmerged while #118 owns the exact v0.6.0 release/publication boundary. Before any lifecycle transition refetch exact head/live base, ancestry, rules/permissions, reviews/threads and every applicable repository/central workflow. Do not create a competing Hangul writer, transfer predecessor evidence, self-approve, weaken gates, move protected main or fabricate release identity.

Close this issue only after #320 integrates under live governance and the resulting protected-main generation proves the feature on that exact integrated head.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: dependenciesDependency or lockfile maintenancearea: securitySecurity boundary, hardening, or vulnerability preventionpriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: featureNew or expanded product capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions