Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
c9f99c8
feat(ui): publish editor chrome tokens and Storybook inventory
cursoragent Aug 16, 2026
df74810
fix(docs): renumber design-token ADR to 0031
seonghobae Aug 16, 2026
720beff
fix(docs): index design-token ADR as 0031
seonghobae Aug 16, 2026
89dd568
test(docs): bind design-token contract to ADR 0031
seonghobae Aug 16, 2026
89dcc2a
fix(docs): align design-token fitness with ADR 0031
seonghobae Aug 16, 2026
d99cf3a
fix(ui): retire colliding token ADR 0027 and name print values
cursoragent Aug 16, 2026
7f734e5
feat(ui): mount shipped Toolbar in Storybook token inventory
cursoragent Aug 16, 2026
c9615d9
feat(ui): publish WCAG contrast checks for editor chrome tokens
cursoragent Aug 16, 2026
03a823d
fix(ui): disclose inventoried active-chrome contrast below 4.5:1
cursoragent Aug 16, 2026
a831359
test(a11y): require compliant dark active-toolbar contrast
seonghobae Aug 16, 2026
837560a
fix(a11y): raise dark active-toolbar contrast
seonghobae Aug 16, 2026
081f1a6
fix(a11y): ship compliant dark active-toolbar accent
seonghobae Aug 16, 2026
a2cf525
test(a11y): bind docs to compliant shipped active contrast
seonghobae Aug 16, 2026
c92bcd5
docs(a11y): record compliant shipped dark active contrast
seonghobae Aug 16, 2026
119c4e3
docs(a11y): distinguish shipped contrast from host overrides
seonghobae Aug 16, 2026
f0afb6f
docs(adr): own default active-toolbar contrast
seonghobae Aug 16, 2026
8b7bccb
docs(changelog): record dark active-toolbar contrast fix
seonghobae Aug 16, 2026
57413d5
test(a11y): distinguish default repair from host re-theming
seonghobae Aug 16, 2026
d22a8d5
docs(a11y): separate shipped defaults from host re-theming
seonghobae Aug 16, 2026
8c853e7
test(a11y): align re-theming contract with shipped defaults
seonghobae Aug 16, 2026
1fd0bdc
test(a11y): distinguish historical contrast defect from shipped truth
seonghobae Aug 16, 2026
d4a2311
test(a11y): cover low-contrast host guidance
seonghobae Aug 16, 2026
7ba4788
merge main: preserve release exact-checkout fix for accessibility repair
seonghobae Aug 18, 2026
e4a14d1
test(tokens): require DTCG 2025.10 value shapes
seonghobae Aug 18, 2026
4505293
fix(tokens): emit DTCG 2025.10 native values
seonghobae Aug 18, 2026
3cc73f5
test(release): require four-file canonical inventory
seonghobae Aug 18, 2026
c1429c3
docs(release): align contracts with four-file inventory
seonghobae Aug 18, 2026
d36c2e8
docs(release): align test strategy with four-file inventory
seonghobae Aug 18, 2026
938640a
docs(release): align operability with four-file inventory
seonghobae Aug 18, 2026
a74d336
docs(release): supersede stale three-file doctoring
seonghobae Aug 18, 2026
0f7d3bd
test(docs): reject active-PR shipped theme claims
seonghobae Aug 18, 2026
6d5dbe7
test(docs): narrow active-PR truth contract
seonghobae Aug 18, 2026
24e5195
test(release): include changelog in four-asset contract
seonghobae Aug 18, 2026
15486eb
docs(theme): separate active repair from shipped defaults
seonghobae Aug 18, 2026
cfa8a2f
docs(storybook): label repaired contrast as active PR
seonghobae Aug 18, 2026
affd46a
docs(doctoring): separate proposal from shipped truth
seonghobae Aug 18, 2026
d0b3494
docs(adr): keep proposed theme decision non-shipped
seonghobae Aug 18, 2026
2a23839
docs(changelog): converge active and release truth
seonghobae Aug 18, 2026
bb49858
test(a11y): require actionable override contrast guidance
seonghobae Aug 18, 2026
8df9736
fix(a11y): distinguish catalog and override contrast checks
seonghobae Aug 18, 2026
4cce549
test(docs): require truthful override contrast guidance
seonghobae Aug 18, 2026
0ddf23b
docs(a11y): distinguish catalog and resolved override contrast
seonghobae Aug 18, 2026
c25607e
fix(a11y): preserve actionable override instruction contract
seonghobae Aug 18, 2026
c7ea338
docs(a11y): bind custom themes to resolved contrast values
seonghobae Aug 18, 2026
9f1f6e5
docs(adr): separate catalog and custom-theme contrast authority
seonghobae Aug 18, 2026
ce078cf
docs(a11y): make host theme contrast verification truthful
seonghobae Aug 18, 2026
92d8f5a
fix(a11y): align contrast guidance with exact contracts
seonghobae Aug 18, 2026
93bb31c
docs(a11y): make token inventory authority explicit
seonghobae Aug 18, 2026
db52724
test(release): cover release-security stale inventory phrases
seonghobae Aug 18, 2026
422b0be
docs(a11y): clarify catalog versus resolved override contrast
seonghobae Aug 18, 2026
f20cadb
docs: reconcile protected DOCX hyperlink maturity
seonghobae Aug 19, 2026
ac23bc2
test: lock protected DOCX hyperlink documentation maturity
seonghobae Aug 19, 2026
4d33e4c
test(design-tokens): reject hostile contrast color coercion
seonghobae Aug 19, 2026
d56be5a
fix(design-tokens): reject hostile contrast inputs
seonghobae Aug 19, 2026
b20d534
test(design-tokens): require immutable DTCG font values
seonghobae Aug 19, 2026
0dbb7f4
fix(design-tokens): freeze DTCG font values
seonghobae Aug 19, 2026
08b576e
test(a11y): expose missing editor focus indicator
seonghobae Aug 20, 2026
44807c9
fix(a11y): restore visible editor keyboard focus
seonghobae Aug 20, 2026
0a5f18b
test(a11y): verify packed editor focus indicator
seonghobae Aug 20, 2026
94b9a23
test(a11y): run focus acceptance cross-engine
seonghobae Aug 20, 2026
97cce96
test(print): reject focus chrome in paged output
seonghobae Aug 20, 2026
082c19e
fix(print): suppress interactive focus chrome
seonghobae Aug 20, 2026
e2c4dc8
test(print): assert rendered outline suppression
seonghobae Aug 20, 2026
e56301c
docs(changelog): record editor focus accessibility contract
seonghobae Aug 20, 2026
6778fe1
test(docs): reject stale protected-capability maturity
seonghobae Aug 20, 2026
6bcb6ab
docs(architecture): align protected package and print maturity
seonghobae Aug 20, 2026
fcaf68e
chore(ownership): restore release-blocker scope
seonghobae Aug 20, 2026
11d5cfe
chore(ownership): remove duplicate maturity contract
seonghobae Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ htmlcov/

# CodeGraph local index
.codegraph/

# Storybook local build output
storybook-static/
9 changes: 9 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
framework: '@storybook/react-vite',
stories: ['../stories/**/*.stories.@(ts|tsx)'],
addons: ['@storybook/addon-docs'],
};

export default config;
11 changes: 11 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { Preview } from '@storybook/react';

import '../src/styles.css';

const preview: Preview = {
parameters: {
controls: { disable: true },
},
};

export default preview;
2 changes: 2 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ The protected standalone product provides:
- dependency-locked Chromium/Firefox/WebKit rich-clipboard release assurance; and
- a network-free Office renderer for deterministic DOCX, XLSX, and PPTX output.

A named editor-chrome theme-token catalog and Storybook inventory for repeating toolbar/editor objects are Active PR / Proposed. Hosts override `--cwl-*` on `.cwl-editor`; Inkspan does not own Figma Variables, brand certification, or design-tool sync.

Hosts own transport, authorization, tenant isolation, persistence, credentials, migration, retention, and model-use policy. They also own authentication, deployment, durable audit, print destination policy, and any durable PDF/print-service authority; persistence includes durable storage and commit authority.

Inkspan therefore never opens a production collaboration connection, chooses a tenant, stores a provider secret, creates a durable database transaction, decides a retention schedule, authorizes an AI operation, or claims that a browser print destination constitutes a durable authorized export. A standalone adopter can provide those capabilities directly; a CWL host can provide them through shared platform services.
Expand Down
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim

## [Unreleased]

### Added
- Named the repeating editor chrome as a host-facing theme-token catalog and Storybook inventory so hosts can override `--cwl-*` custom properties on `.cwl-editor` after checking WCAG 2.2 contrast, without editing Inkspan internals. Color catalog values now distinguish light, dark, and `@media print` remaps; forced-colors mode is not treated as a token assignment. Hosts can call `getEditorThemeTokenContrast()` to compare inventoried pairs, including `--cwl-accent` on `--cwl-accent-soft`, against the 4.5:1 text threshold via `meetsTextContrast`.

### Accessibility
- Prepared the active-PR dark active-toolbar accent change from protected-main `#4493f8` to `#58a6ff`, increasing `--cwl-accent` text on `--cwl-accent-soft: #163356` from about 4.13:1 to about 5.06:1 so the candidate default 13px active-button text meets the WCAG 2.2 4.5:1 normal-text threshold; this remains active-PR evidence until protected integration. `getEditorThemeTokenContrast()` checks catalog values, and host overrides must be re-checked with `contrastRatioFromHex(actualForegroundHex, actualBackgroundHex)` using the actual resolved colors.
- Restored a visible `:focus-visible` indicator on the editable textbox, mapped it to `CanvasText` in forced-colors mode, and suppresses that interactive focus chrome under `@media print`; dependency-locked Chromium, Firefox, and WebKit acceptance exercises the packed stylesheet on the real `role="textbox"` surface.

## [0.6.0] — 2026-08-10

### Release
Expand All @@ -15,7 +22,7 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim
- Added the selected standalone Markdown or HTML value to an explicitly configured SSR native form field, preserving controlled-value precedence, external form association, React attribute escaping, and the synchronous post-hydration TipTap transaction mirror

### Security
- Added a fail-closed draft release asset inventory gate that requires exactly one npm tarball, one Office wheel, and `SHA256SUMS`, rejects stale or unexpected draft assets before immutable publication, and verifies every GitHub-reported `sha256:` asset digest against the transferred local file
- Added a fail-closed draft release asset inventory gate that requires exactly one npm tarball, one Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`, rejects stale or unexpected draft assets before immutable publication, and verifies every GitHub-reported `sha256:` asset digest against the transferred local file
- Kept SSR document disclosure opt-in through `formFieldName`; hidden-field values remain client-controlled submission data and do not replace host authentication, authorization, tenant isolation, CSRF defenses, server validation, durable concurrency, or persistence controls
- Kept collaborative Yjs document content out of server markup until the host-owned client collaboration lifecycle is bound
- Added packed headless Markdown authority verification that rejects external runtime imports, dynamic module loaders, ambient network/environment credential access, React/TipTap/Yjs runtime coupling, CWL host coupling, and model credential references from the dedicated conversion artifact
Expand Down Expand Up @@ -106,7 +113,7 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim
- Corrected the autosave onboarding so initial and replacement validators are checked before use and come from the durable host's server-issued strong `ETag` rather than local revision evidence; missing, weak, or malformed validators fail closed in the example
- Documented that host-owned save callbacks must apply their own timeout or abort signal because an unresolved callback intentionally retains the active single-flight operation; retry policy remains host-owned
- Added a deterministic repository contract test and APA 7th-style doctoring for README, npm-search, Node.js package-export discoverability, RFC 9110 validator ownership, and quoted opaque-tag syntax
- Added operator, doctoring, and release evidence for the durable autosave session, coherent recovery-time flush snapshots, host ownership boundaries, exact-head verification, and acquisition-review scope
- Added operator, doctoring, and release evidence for the durable autosave session, coherent recovery-time flush snapshots, exact-head verification, and acquisition-review scope

## [0.5.28] — 2026-08-05

Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,25 @@ export function Example() {
Set `mode="html"` when `value` and `onChange` should exchange HTML. Both modes
embed accepted images as inline data URIs.

### Theme the repeating chrome

Override the named `--cwl-*` custom properties on `.cwl-editor` after checking
WCAG 2.2 contrast for body text and active toolbar text. Use
`getEditorThemeTokenContrast('cwl-accent', 'cwl-accent-soft', 'dark')` to inspect
Inkspan's catalog baseline. After overriding CSS, pass the actual resolved
foreground/background hex values to `contrastRatioFromHex()` before shipping the
host theme. Do not edit Inkspan internals. See
[`docs/design-tokens.md`](docs/design-tokens.md) for the token catalog and
[`docs/storybook-inventory.md`](docs/storybook-inventory.md) for the Storybook
preview of toolbar and editor chrome.

```css
.cwl-editor {
--cwl-accent: #0b6e4f;
--cwl-accent-soft: #d8f3e8;
}
```

### Server rendering

`CwlEditor` and `CollaborativeCwlEditor` are safe to include in server-rendered
Expand Down
5 changes: 3 additions & 2 deletions docs/CONTRACTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Expected degraded states are explicit rather than mapped to false success:

A public release binds one exact integrated protected source head to package/artifact identity, applicable CI/security/accessibility/document-fidelity evidence, owned production coverage, public-docstring evidence, SBOM/provenance/reproducibility where configured, formal review requirements, rollback guidance, and post-publication smoke verification.

Before immutable publication, the canonical draft inventory is **exactly three regular top-level files**: exactly one npm tarball, exactly one Inkspan Office wheel, and `SHA256SUMS`. Missing, stale, unexpected, duplicate, non-regular, incompletely uploaded, or digest-mismatched assets fail closed. After upload and before publication, the authenticated paginated GitHub Releases API inventory must equal the local release directory by exact asset name, every remote asset must report an uploaded state, and every GitHub-reported `sha256:` digest must equal the digest of the exact transferred local file. The workflow does not silently delete an unexpected remote asset to make an ambiguous draft look clean.
Before immutable publication, the canonical draft inventory is **exactly four regular top-level files**: exactly one npm tarball, exactly one Inkspan Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`. Missing, stale, unexpected, duplicate, non-regular, incompletely uploaded, or digest-mismatched assets fail closed. After upload and before publication, the authenticated paginated GitHub Releases API inventory must equal the local release directory by exact asset name, every remote asset must report an uploaded state, and every GitHub-reported `sha256:` digest must equal the digest of the exact transferred local file. The workflow does not silently delete an unexpected remote asset to make an ambiguous draft look clean.

Rollback must preserve readable canonical documents and must not require silently reinterpreting persisted schema or selector-projection semantics. Host-owned migrations, persistence rollback, annotation re-anchoring, tenant recovery, and deployment rollback remain host responsibilities unless a future versioned contract explicitly assigns them to Inkspan.

Expand All @@ -152,9 +152,10 @@ Rollback must preserve readable canonical documents and must not require silentl
| autosave | local ordering/state, callback contract, validator validation | transport, durable CAS, retry/offline policy, persistence |
| collaboration | provider-neutral editor/Yjs binding | provider lifecycle, rooms, identity, authorization, persistence, awareness privacy |
| Office rendering | deterministic bounded JSON→artifact conversion | file destination policy, downstream distribution, tenant authorization |
| editor chrome theming (Active PR / Proposed) | named `--cwl-*` tokens, DTCG interchange snapshot, Storybook inventory, inventoried pair contrast including `--cwl-accent` on `--cwl-accent-soft` | host brand CSS, contrast certification, Figma Variables, design-tool sync |
| naruon composition | stable local package/module boundary | authenticated compose transport, tenancy, provider/model policy |
| model assistance | deterministic proposal acceptance boundary | provider, prompt/data policy, credentials, human approval |
| release evidence | exact three-file draft inventory, package/artifact/digest verification and repository evidence | downstream deployment and operational rollout |
| release evidence | exact four-file draft inventory, package/artifact/digest verification and repository evidence | downstream deployment and operational rollout |

## Related canonical documents

Expand Down
2 changes: 2 additions & 0 deletions docs/DOCUMENTATION_FITNESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Document fitness and implementation maturity are independent. A `present_current
| Unified stable registry release train | ADR 0019, protected release workflow and release doctoring | `present_current` | `implemented_on_protected_main` | Stable npm/Office version equality, OIDC Trusted Publishing, exact-artifact publication and post-publication digest verification are source-integrated; live registry publication remains separate operational evidence. |
| Framework-neutral Markdown package boundary | ADR 0020, protected `@contextualwisdomlab/cwl-editor/markdown` package subpath and shared policy modules from #114 | `present_current` | `implemented_on_protected_main` | Server/worker consumers can reuse deterministic Markdown/HTML/email/plain-text conversion without evaluating the React/TipTap editor graph. |
| CSS paged-media print boundary | ADR 0021, protected `src/styles.css`, packaged stylesheet evidence and real-browser print tests from #116/#127 | `present_current` | `implemented_on_protected_main` | Declarative print output removes screen-only clipping/chrome while preserving authored content without creating a durable PDF service. |
| Editor chrome design tokens / Storybook inventory | ADR 0031, `docs/design-tokens.md`, doctoring, token catalog, and Storybook stories | `present_current` | `implemented_on_active_pr` | Hosts can name, override, and preview repeating toolbar/editor tokens without treating the interchange snapshot as shipped protected-main authority. |
| Informative DOCX PNG figures | ADR 0022, Office schema/renderer/tests and guidance | `present_current` | `implemented_on_protected_main` | Strict bounded inline PNG figures preserve informative alternative text without remote-resource or arbitrary OOXML authority. |
| DOCX bounded rich-text runs | ADR 0023, Office schema/renderer/tests and doctoring | `present_current` | `implemented_on_protected_main` | Ordered bold/italic/underline runs preserve common inline fidelity under one bounded deterministic contract. |
| DOCX bounded paragraph alignment | ADR 0024, Office schema/renderer/tests, Office guidance and doctoring | `present_current` | `implemented_on_protected_main` | `paragraph` and `rich_paragraph` preserve explicit left/center/right/justify alignment while omission retains inherited/default behavior. |
Expand All @@ -82,6 +83,7 @@ The documentation pack is substantially complete for acquisition review, but rep
1. The protected manifests now agree at `0.6.0`, while registry operational acceptance remains open under issue #118 because the exact protected release still needs its tag/GitHub Release, live npm/PyPI Trusted Publisher execution, and public artifact digest verification.
2. Future protected-source changes must continue to reconcile PRD/TRD/Architecture/ADR/UML/DATA_MODEL/security/test/operability/traceability semantics rather than treating this baseline as permanently complete.
3. Documentation becoming mergeable, green, or protected-merged is never a reason for the commercial loop to stop; the next safe product, release, security, accessibility, package, Office-fidelity, or interoperability lane continues.
4. Hosts still need a named, Storybook-previewable chrome-token catalog so brand theming does not require editing Inkspan internals; that lane is Active PR / Proposed and must not be described as shipped until protected integration.

## Sufficiency decision

Expand Down
2 changes: 1 addition & 1 deletion docs/OPERABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Release publication occurs only from an exact integrated protected head. The rel
Before publication:

1. fetch the current protected `main` ref and require the release tag event commit SHA to equal that exact integration tip, not merely be an ancestor of it;
2. build exactly three regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, and `SHA256SUMS`;
2. build exactly four regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`;
3. reject missing, duplicate, non-regular, stale, or unexpected local entries and verify the local digests;
4. after upload, query the authenticated paginated GitHub Releases API and require the resumed remote draft asset-name set to equal the local release directory exactly;
5. require every remote asset state to be uploaded and every GitHub-reported `sha256:` digest to equal the exact transferred local file digest;
Expand Down
2 changes: 2 additions & 0 deletions docs/PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,5 @@ Shareable acquisition evidence excludes production tenant content and credential
Protected `main` is the sole implemented baseline. Open PRs may describe Proposed or Active work but are not shipped contracts until protected integration. Canonical documentation must state when a requirement is target architecture rather than current implementation.

SafeClipboard, real Chromium/Firefox/WebKit release assurance, lifecycle observation, the root security disclosure lifecycle, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, W3C text-position selector evidence, document-transition evidence, and envelope identity migration routing are implemented on protected `main`.

A named editor-chrome theme-token catalog, DTCG 2025.10 interchange snapshot, and Storybook inventory for repeating toolbar/editor objects are Active PR / Proposed and are not shipped claims until protected integration. Hosts must check inventoried active-chrome contrast (`--cwl-accent` on `--cwl-accent-soft`) in addition to body text.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This directory is the discoverable index for Inkspan's product, technical, secur
| [`package-distribution.md`](package-distribution.md) | Buyer-facing public npm package entrypoints, packaged contents, runtime dependency boundaries, and consumer verification |
| [`email-output.md`](email-output.md) | Deterministic email fragment/full-document authority, language/direction metadata, accessibility and host-owned transport boundary |
| [`print-output.md`](print-output.md) | Browser print/paged-media presentation, accessibility/fidelity limits, host-owned governed-export boundary, and rollback |
| [`design-tokens.md`](design-tokens.md) | Host-facing editor chrome tokens, DTCG 2025.10 interchange snapshot, and Storybook inventory (Active PR / Proposed) |
| [`UML.md`](UML.md) | Component, sequence, state and authority-flow diagrams |
| [`DATA_MODEL.md`](DATA_MODEL.md) | Conceptual evidence/domain model and persistence ownership |
| [`THREAT_MODEL.md`](THREAT_MODEL.md) | Trust boundaries, abuse cases, security/privacy controls and residual risks |
Expand Down
Loading
Loading