Skip to content

fix(accessibility): validate editor language tags before emitting lang #233

Description

@seonghobae

Buyer-visible accessibility/data-integrity boundary

Protected main@3b38ead2d00f44eb578d0689087b9293b3dabe1e documents languageTag as BCP 47 metadata, while the historical runtime path trimmed and emitted any in-bound string directly as the editable surface's HTML lang attribute. An untyped/deserialized malformed host value could therefore silently produce invalid language metadata for authored content and assistive technology.

Inkspan owns only validation of its public local attribute contract. Host language choice/localization and registry-content policy remain host-owned; this adds no inference, transport, persistence, credentials, tenancy, model/provider, network, runtime registry, or durable-audit authority.

Standards correction and canonical owner

RFC 5646 Language-Tag includes normal langtag, private-use, and grandfathered syntax. ECMA-402 Intl.getCanonicalLocales() is a narrower locale-processing boundary and rejected valid RFC 5646 forms exercised by this lane, including private-use-only x-private, grandfathered i-klingon, and extlang zh-cmn-Hans-CN. Platform locale canonicalization is therefore not a valid substitute for Inkspan's declared syntax contract.

Draft PR #230 is the sole active writer for src/components/editorAccessibility.ts and focused metadata/runtime tests. At exact head 59d82f8b65cfad5230fa9e11afb97867293a43f5, the branch uses local deterministic RFC 5646 well-formed-syntax validation for the portions that can be decided without an IANA registry snapshot, including private-use-only, grandfathered, permanent extlang position, script/region/variant/extension/private-use sequences, duplicate variants, and duplicate extension singletons. Accepted tags preserve the caller's trimmed spelling; Inkspan does not infer, alias-normalize, case-normalize, or claim registry-content validity.

TDD / exact-current evidence

  • The initial malformed-tag RED established that a non-blank malformed runtime languageTag was emitted instead of rejected.
  • Test-only 64e46d780cd25bbcc9b821470b641f48820b7e63 proved the first Intl.getCanonicalLocales() remedy was too narrow; hosted CI 31534174592 failed the RFC 5646 preservation regressions for x-private, i-klingon, and zh-cmn-Hans-CN.
  • Invalid extlang-position RED lineage is 0551ae31809dc37e146f1bba60bf5d13daf04b60.
  • Exact-current fix(accessibility): harden editor metadata runtime contracts #230 repository workflows are terminal success: CI 32322070195, Security Scan 32322070146, and SAST Semgrep 32322070224. Predecessor evidence does not transfer.

Acceptance

  1. Reject malformed bounded runtime language tags with the stable payload-redacted local error contract while preserving blank-as-absent behavior.
  2. Preserve complete locally decidable RFC 5646 well-formed syntax, including private-use-only, grandfathered, extlang, script/region/variant/extension/private-use sequences; do not substitute narrower ECMA-402 locale grammar.
  3. Preserve the caller's accepted trimmed spelling rather than silently canonicalizing it.
  4. Do not infer language, normalize aliases/case, echo rejected values, or add model/network/runtime-registry dependencies. Registry-content validity remains host policy.
  5. Preserve accessibility metadata bounds, accessible-name precedence, direction and ARIA state behavior.
  6. Maintain exact owned-production coverage and all applicable package/browser/Office/security gates on the eventual integration head.
  7. Close only when canonical fix(accessibility): harden editor metadata runtime contracts #230 integrates into protected main; Draft/head-green evidence is not protected shipped truth.

Integration boundary

Keep #230 Draft/unmerged while #118 freezes protected main for v0.6.0 operational acceptance and while qualifying independent approval plus every then-live merge/review/governance gate remain incomplete. Never transfer predecessor CI/review evidence or create a competing writer for the same source.

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: bugDefect or incorrect behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions