From d3d91c8ad66b7a3e91b2813293fca091ece08ba9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 19:43:04 +0900 Subject: [PATCH 001/101] docs: add canonical Inkspan product requirements --- docs/PRD.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/PRD.md diff --git a/docs/PRD.md b/docs/PRD.md new file mode 100644 index 00000000..98c06f1d --- /dev/null +++ b/docs/PRD.md @@ -0,0 +1,59 @@ +# Inkspan Product Requirements + +Status: Proposed canonical baseline + +## Product + +Inkspan is a standalone rich-text authoring package and an embeddable CWL editor/conversion module. It gives hosts deterministic authoring, conversion, revision evidence, safe clipboard handling, SSR/form integration, local autosave coordination, and provider-neutral collaboration bindings without taking ownership of host transport, identity, tenancy, durable persistence, credentials, retention, deployment, or model-use policy. + +## Users and buyers + +- Application developers embedding an editor into web and SSR applications. +- Enterprise platform teams requiring deterministic conversion, evidence, accessibility, security boundaries, and reproducible packages. +- CWL products such as naruon that compose Inkspan through stable package contracts. +- Operators and acquisition reviewers who need explicit ownership, release, security, and rollback evidence. + +## Required outcomes + +1. Author Markdown and HTML through a deterministic TipTap/ProseMirror surface. +2. Reject or sanitize unsafe rich clipboard input before it becomes editor state. +3. Produce versioned canonical document envelopes and SHA-256 revision evidence. +4. Bind selections and transitions to exact document revisions without copying document bodies into ordinary evidence metadata. +5. Support SSR-safe hydration and optional native form serialization while treating browser-submitted values as untrusted host input. +6. Coordinate bounded single-flight autosave with explicit conflict/failure recovery and server-selected strong validators. +7. Expose lifecycle observation only for externally visible state changes; construction and no-op operations must not manufacture lifecycle notifications. +8. Provide provider-neutral collaboration bindings while hosts retain collaboration transport, authorization, tenant isolation and durable audit ownership. +9. Preserve accessible keyboard, status and toolbar semantics. +10. Produce reproducible package and release evidence with fail-closed publication checks. + +## Non-goals + +Inkspan is not an identity provider, tenant database, durable document store, collaboration authorization server, deployment platform, model router, durable audit service, or merge/release authority for host applications. + +## Security and privacy requirements + +- Untrusted HTML, DOM capabilities, clipboard configuration, form values and host callbacks fail closed at documented boundaries. +- Active or hidden rich content must not bypass the supported semantic clipboard policy. +- Revision/entity tags are equality metadata, not credentials or authorization. +- Document bodies must not enter ordinary lifecycle, selection or transition evidence unless an explicit versioned contract requires them. +- Host applications remain responsible for authentication, authorization, CSRF, tenant isolation, persistence and retention. + +## Reliability and concurrency requirements + +- Autosave remains single-flight with bounded pending work. +- Conflict and ambiguous failure never silently advance durable validators. +- Observer failures cannot change save ordering or outcomes. +- No-op lifecycle operations must not emit a synthetic initial or duplicate snapshot. +- Async revision/selection capture must bind to one immutable editor state. + +## Accessibility requirements + +Native controls, focus behavior, shortcut metadata and host-facing lifecycle state must support WCAG-oriented embedding. Machine state is not user-facing wording; localization and application-level live-region policy remain host responsibilities. + +## Packaging and release acceptance + +A release is acceptable only from an exact integrated protected head with required CI/security checks, exact owned production coverage, package-consumer compatibility, reproducibility/provenance evidence, zero valid unresolved findings, required independent review, rollback guidance and verified release artifacts. + +## Current and planned scope + +Protected main is the authority for implemented behavior. Open PRs may describe Proposed/Active work but are not shipped contracts until protected integration. Provider-neutral collaboration, autosave, review evidence and release hardening evolve through versioned public contracts rather than hidden host coupling. From b8c2c3d151922e9908908a4e6ba0d1c886023248 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 19:43:18 +0900 Subject: [PATCH 002/101] docs: add canonical Inkspan technical requirements --- docs/TRD.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs/TRD.md diff --git a/docs/TRD.md b/docs/TRD.md new file mode 100644 index 00000000..9a28342a --- /dev/null +++ b/docs/TRD.md @@ -0,0 +1,53 @@ +# Inkspan Technical Requirements + +Status: Proposed canonical baseline + +## Runtime boundary + +Inkspan owns deterministic editor, conversion and local coordination code. Hosts own network transport, authentication/authorization, tenant isolation, durable persistence, credentials, migrations, retention, durable audit storage, deployment and model-use policy. + +## Document identity + +A versioned document envelope is validated before canonicalization or hashing. SHA-256 revision evidence identifies exact canonical content. Local content digests do not replace server-selected RFC 9110 strong validators for durable compare-and-swap. + +## Clipboard boundary + +Rich clipboard HTML is untrusted. Sanitization must be installed in the actual TipTap v2/ProseMirror paste pipeline, use bounded fail-closed validation, avoid external fetch or active execution, and preserve only supported semantic content. Pure sanitizer APIs and editor integration must remain behaviorally consistent. + +## SSR and native forms + +Server rendering must not instantiate an editor view. When a native field is explicitly enabled, SSR/hydration serializes the selected controlled value as escaped input data. The value is client-controlled submission data, never authorization, CSRF protection, signature or durable-write evidence. + +## Revision-scoped evidence + +Selection evidence captures selection coordinates and revision from the same immutable editor state before asynchronous hashing. Transition evidence validates previous and resulting envelopes before sequential revision derivation and contains revision metadata rather than document bodies. + +## Autosave state machine + +States are `idle`, `saving`, `blocked`, `closing`, and `closed`, with explicit blocked reasons. The queue retains bounded active/pending work and exposes immutable document-free snapshots. Durable sessions carry a host-owned strong validator that advances only after a validated saved result. + +Lifecycle observers are optional and bounded to one construction-time callback. They receive only distinct externally visible state snapshots. Construction emits nothing. A method call that produces no externally visible state transition, including `resume()` returning false, emits nothing. Observer exceptions are isolated from persistence behavior. + +## Collaboration + +Collaboration bindings are provider-neutral. Inkspan may adapt editor state to Yjs-compatible surfaces, but provider lifecycle, identity, awareness privacy, tenant authorization, persistence and durable audit remain host responsibilities. + +## Failure semantics + +Public failures are bounded and redacted. Host callback exceptions, malformed callback results, hostile reflection/accessors, invalid envelopes, invalid UTF-8 and unsafe clipboard input must not leak private values or silently succeed. Cancellation and host-owned transport policy remain explicit. + +## Accessibility + +Shipped keyboard behavior and programmatic shortcut metadata must agree. Host-visible save/conflict state must be sufficient for accessible application messaging without prescribing localized wording. + +## Packaging and compatibility + +The root package and framework-independent subpaths must remain consumable from packed ESM/CommonJS and strict TypeScript environments without accidental React/DOM/framework dependencies where the subpath contract excludes them. Office artifacts follow their separately versioned package contract. + +## Evidence and governance + +Check runs, commit statuses, automated model verdicts, formal reviews and merge authority are distinct evidence classes. Exact-head evidence does not transfer after source movement. Comments or textual approvals are not formal approval. Release publication must fail closed on ambiguous/stale artifact inventory or digest mismatch. + +## Implemented versus planned + +Protected `main` is the sole implemented baseline. Open PRs are Active/Proposed evidence only until protected merge. Documentation must not convert an unmerged feature into an Accepted shipped claim. From 6550b63d2bf80b3667a5ae8671c8613992e9a4cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 19:43:53 +0900 Subject: [PATCH 003/101] docs: add Inkspan conceptual data model --- docs/DATA_MODEL.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/DATA_MODEL.md diff --git a/docs/DATA_MODEL.md b/docs/DATA_MODEL.md new file mode 100644 index 00000000..0744ef06 --- /dev/null +++ b/docs/DATA_MODEL.md @@ -0,0 +1,40 @@ +# Inkspan Conceptual Data and Evidence Model + +Status: Proposed canonical baseline + +Inkspan does not own an application database. This document is a conceptual/logical model of value objects and host boundaries; it must not be read as physical DDL. + +```mermaid +erDiagram + document_envelope ||--|| document_revision : derives + document_revision ||--o{ document_transition : previous_or_resulting + document_revision ||--o{ selection_evidence : binds + document_revision ||--o{ autosave_revision : queues + autosave_revision }o--|| autosave_snapshot : appears_in + durable_validator ||--o{ autosave_snapshot : accompanies + collaboration_session }o--o{ document_revision : coordinates + clipboard_policy ||--o{ document_envelope : constrains_input + release_artifact }o--|| release_evidence : verified_by +``` + +## Entities + +- `document_envelope`: versioned validated canonicalizable document value. In-memory/package value; host may persist it. +- `document_revision`: SHA-256 equality evidence derived from one validated canonical envelope. Value object, not authorization. +- `document_transition`: previous/resulting revision pair plus changed classification. Value object without document body. +- `selection_evidence`: ProseMirror structural coordinates bound to one exact revision. Value object, not a durable cross-revision anchor. +- `autosave_revision`: detached immutable revision evidence accepted by local autosave coordination. +- `autosave_snapshot`: frozen document-free queue/session lifecycle metadata. +- `durable_validator`: host/server-selected strong HTTP entity tag used for durable compare-and-swap. Host-owned concurrency evidence. +- `collaboration_session`: conceptual host/provider lifecycle around collaborative editor state. Provider/authorization/persistence are host-owned. +- `clipboard_policy`: bounded local policy controlling accepted rich clipboard semantics. +- `release_artifact`: package/wheel/checksum artifact considered for release. +- `release_evidence`: digest/inventory/provenance evidence used before publication. + +## Ownership + +Inkspan owns deterministic construction and validation of its value objects. Hosts own durable identifiers, actors, tenants, timestamps, storage records, credentials, audit events, authorization decisions, retention and migrations unless a future explicit versioned contract states otherwise. + +## Persistence non-applicability + +No Inkspan-owned relational schema is required by the current architecture. If Inkspan later introduces durable persistence, that is a material architecture change requiring an ADR, migration/rollback design, security review and a physical ERD distinct from this conceptual model. From 302e4a05b0b758c3176f6ad17cc8826c5c9751ca Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 19:44:08 +0900 Subject: [PATCH 004/101] docs: add Inkspan ADR index --- docs/adr/README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 docs/adr/README.md diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 00000000..51211259 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,54 @@ +# Inkspan Architecture Decision Records + +Status values: Proposed, Accepted, Superseded. + +This index records durable architectural decisions. Protected-main implementation is required before a feature-specific decision may be treated as shipped behavior. + +| ADR | Status | Decision | +|---|---|---| +| 0001 | Proposed | Product and host authority boundary | +| 0002 | Proposed | Canonical document and revision evidence | +| 0003 | Proposed | Safe rich clipboard boundary | +| 0004 | Proposed | Strong durable validator and bounded autosave | +| 0005 | Proposed | Revision-scoped review evidence | +| 0006 | Proposed | SSR/native form client-controlled boundary | +| 0007 | Proposed | Provider-neutral collaboration ownership | +| 0008 | Proposed | Release evidence and independent governance | + +## Decision summaries + +### ADR-0001 Product and host authority boundary + +Inkspan owns editor, deterministic conversion and local coordination. Hosts own transport, authentication/authorization, tenancy, durable persistence, credentials, migration, retention, durable audit, deployment and model policy. Alternative rejected: an editor package that silently becomes the host platform. + +### ADR-0002 Canonical document and revision evidence + +Validate a versioned document envelope before deterministic canonicalization and SHA-256 revision derivation. Revision tags are equality evidence, not identity or authorization. Alternative rejected: hashing arbitrary editor/JSON serialization. + +### ADR-0003 Safe rich clipboard boundary + +Treat rich HTML as untrusted and sanitize through a bounded fail-closed semantic policy installed in the actual ProseMirror paste path. Alternative rejected: UI-only/manual sanitizer calls that do not protect real paste behavior. + +### ADR-0004 Strong durable validator and bounded autosave + +Use bounded single-flight local autosave. A server-selected strong validator is host-owned compare-and-swap evidence and advances only on validated durable success. Lifecycle observation reports only real externally visible transitions; construction and no-op operations emit nothing. Alternative rejected: treating a local content digest as durable server concurrency authority or allowing polling/subscriber growth to become persistence control. + +### ADR-0005 Revision-scoped review evidence + +Selections and document transitions are bound to exact revisions while ordinary evidence omits document bodies. Alternative rejected: copying selected/document text into every evidence object or reusing structural coordinates across revisions without explicit re-anchoring. + +### ADR-0006 SSR/native form client-controlled boundary + +Optional native form serialization is escaped SSR/hydration data and synchronously mirrors editor transactions, but submitted values remain untrusted client input. Alternative rejected: treating hidden fields as authorization, integrity or CSRF evidence. + +### ADR-0007 Provider-neutral collaboration ownership + +Inkspan exposes collaboration adapters without owning provider transport, tenant authorization, identity, durable collaboration storage or audit. Alternative rejected: coupling the package to one provider or application database. + +### ADR-0008 Release evidence and independent governance + +Exact-head CI/security/package/provenance evidence, formal independent review where required, and fail-closed release-asset verification are separate authorities. Comments, statuses and predecessor evidence do not become formal approval. Alternative rejected: publication or merge from stale/ambiguous evidence. + +## ADR quality requirements + +Material follow-up ADRs must record context, alternatives, decision, consequences, security/privacy impact, failure/recovery, acceptance tests, migration/rollback and supersession conditions. Detailed standalone ADR files should replace these summaries as decisions evolve; the index remains authoritative for status and discovery. From 5d5b8c676f3cbed1d00121e44050e95a04198396 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 19:44:18 +0900 Subject: [PATCH 005/101] docs: add Inkspan runtime diagrams --- docs/UML.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 docs/UML.md diff --git a/docs/UML.md b/docs/UML.md new file mode 100644 index 00000000..f9fd0ed6 --- /dev/null +++ b/docs/UML.md @@ -0,0 +1,112 @@ +# Inkspan Runtime Diagrams + +Status: Proposed canonical baseline + +## Component topology + +```mermaid +flowchart LR + HostApp[Host application] --> EditorCore[Inkspan editor] + EditorCore --> ConversionCore[Deterministic conversion] + EditorCore --> ClipboardBoundary[Safe clipboard] + EditorCore --> EvidenceCore[Revision and selection evidence] + EditorCore --> AutosaveCore[Local autosave coordinator] + EditorCore --> CollaborationAdapter[Provider-neutral collaboration adapter] + AutosaveCore --> HostSave[Host durable save callback] + CollaborationAdapter --> HostProvider[Host collaboration provider] + HostApp --> HostAuthority[Host auth tenancy persistence audit] +``` + +## Paste sequence + +```mermaid +sequenceDiagram + participant UserClipboard + participant PastePipeline + participant SafeClipboard + participant EditorState + UserClipboard->>PastePipeline: rich HTML + PastePipeline->>SafeClipboard: transform pasted HTML + SafeClipboard->>SafeClipboard: bounded inert parse and allowlist + SafeClipboard-->>PastePipeline: sanitized content or bounded failure + PastePipeline->>EditorState: parse and transact only accepted content +``` + +## Autosave sequence and no-op rule + +```mermaid +sequenceDiagram + participant Host + participant Queue + participant DurableSave + Host->>Queue: enqueue revision evidence + Queue-->>Host: saving snapshot when observer exists + Queue->>DurableSave: one active save + DurableSave-->>Queue: saved or conflict/failure + alt saved + Queue-->>Host: next distinct lifecycle snapshot + else blocked + Queue-->>Host: blocked snapshot + Host->>Queue: resume + alt resume changes state + Queue-->>Host: next distinct lifecycle snapshot + else resume is false/no-op + Queue-->>Host: no observer notification + end + end +``` + +## Autosave state machine + +```mermaid +stateDiagram-v2 + [*] --> idle + idle --> saving: enqueue + saving --> idle: saved without pending + saving --> saving: continue pending + saving --> blocked: conflict or failure + blocked --> saving: resume with pending + blocked --> idle: resume without pending + idle --> closed: close + blocked --> closed: close + saving --> closing: close during active save + closing --> closed: active save settles +``` + +## SSR and native form sequence + +```mermaid +sequenceDiagram + participant Server + participant Browser + participant Editor + participant NativeForm + Server-->>Browser: escaped controlled native field value + Browser->>Editor: client hydration and editor creation + Editor->>NativeForm: mirror serialization on document transaction + NativeForm-->>Host: untrusted submitted value +``` + +## Selection and revision capture + +```mermaid +sequenceDiagram + participant Caller + participant EditorState + participant RevisionDerivation + Caller->>EditorState: request selection revision evidence + EditorState->>EditorState: capture one immutable state and selection + EditorState->>RevisionDerivation: canonical envelope from same state + RevisionDerivation-->>Caller: frozen revision and structural coordinates +``` + +## Authority boundaries + +```mermaid +flowchart TB + InkspanAuthority[Inkspan deterministic authority] --> EditorSemantics[Editor conversion revision semantics] + HostAuthority[Host authority] --> HostServices[Transport identity tenancy persistence audit] + MachineEvidence[CI security package provenance] --> ProtectedMerge[Protected merge] + IndependentReview[Independent formal review where required] --> ProtectedMerge + ProtectedMerge --> ReleaseAuthority[Release authority] +``` From 8814c00c383af89a775a522345d86b14b0c18b9d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:03:10 +0900 Subject: [PATCH 006/101] test(docs): require acquisition-complete canonical spine --- src/canonicalProductDocumentation.test.ts | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/canonicalProductDocumentation.test.ts diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts new file mode 100644 index 00000000..dcfdfca9 --- /dev/null +++ b/src/canonicalProductDocumentation.test.ts @@ -0,0 +1,87 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import { describe, expect, it } from 'vitest'; + +const repositoryFile = (path: string): string => + readFileSync(resolve(process.cwd(), path), 'utf8'); + +const requiredFiles = [ + 'docs/PRD.md', + 'docs/TRD.md', + 'docs/UML.md', + 'docs/DATA_MODEL.md', + 'docs/THREAT_MODEL.md', + 'docs/TEST_STRATEGY.md', + 'docs/OPERABILITY.md', + 'docs/TRACEABILITY.md', + 'docs/adr/README.md', + 'docs/adr/0001-product-host-authority.md', + 'docs/adr/0002-document-revision-authority.md', + 'docs/adr/0003-safe-rich-clipboard.md', + 'docs/adr/0004-durable-validator-autosave.md', + 'docs/adr/0005-revision-scoped-review-evidence.md', + 'docs/adr/0006-ssr-native-form-boundary.md', + 'docs/adr/0007-provider-neutral-collaboration.md', + 'docs/adr/0008-deterministic-office-rendering.md', + 'docs/adr/0009-naruon-modular-composition.md', + 'docs/adr/0010-release-evidence-authority.md', +] as const; + +describe('canonical product documentation graph', () => { + it('keeps the acquisition-critical document graph discoverable', () => { + for (const path of requiredFiles) { + expect(existsSync(resolve(process.cwd(), path)), path).toBe(true); + } + }); + + it('records host ownership and deterministic Inkspan authority consistently', () => { + const prd = repositoryFile('docs/PRD.md'); + const trd = repositoryFile('docs/TRD.md'); + const threatModel = repositoryFile('docs/THREAT_MODEL.md'); + const operability = repositoryFile('docs/OPERABILITY.md'); + + for (const document of [prd, trd, threatModel, operability]) { + expect(document).toContain('host'); + expect(document).toMatch(/transport|authorization|tenant|persistence/i); + } + expect(prd).toContain('deterministic'); + expect(trd).toContain('Protected `main`'); + expect(threatModel).toContain('document bodies'); + expect(operability).toContain('rollback'); + }); + + it('documents realistic security, test, and release evidence boundaries', () => { + const threatModel = repositoryFile('docs/THREAT_MODEL.md'); + const testStrategy = repositoryFile('docs/TEST_STRATEGY.md'); + const traceability = repositoryFile('docs/TRACEABILITY.md'); + + expect(threatModel).toContain('clipboard'); + expect(threatModel).toContain('formula'); + expect(threatModel).toContain('Yjs'); + expect(testStrategy).toContain('Chromium'); + expect(testStrategy).toContain('Firefox'); + expect(testStrategy).toContain('WebKit'); + expect(testStrategy).toContain('100%'); + expect(traceability).toContain('RFC 9110'); + expect(traceability).toContain('WCAG 2.2'); + expect(traceability).toContain('Protected `main`'); + }); + + it('keeps detailed ADRs indexed and explicit about failure and rollback', () => { + const index = repositoryFile('docs/adr/README.md'); + + for (const path of requiredFiles.filter((path) => /docs\/adr\/\d{4}-/.test(path))) { + const filename = path.split('/').at(-1); + expect(filename).toBeDefined(); + expect(index).toContain(filename!); + const adr = repositoryFile(path); + expect(adr).toContain('## Context'); + expect(adr).toContain('## Decision'); + expect(adr).toContain('## Consequences'); + expect(adr).toContain('## Failure and recovery'); + expect(adr).toContain('## Verification'); + expect(adr).toContain('## Rollback or supersession'); + } + }); +}); From 4ffca86b277cf5a28ddf8d5a9eb9997097835714 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:03:47 +0900 Subject: [PATCH 007/101] docs(security): define canonical Inkspan threat model --- docs/THREAT_MODEL.md | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 docs/THREAT_MODEL.md diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md new file mode 100644 index 00000000..68dc9088 --- /dev/null +++ b/docs/THREAT_MODEL.md @@ -0,0 +1,87 @@ +# Inkspan Threat Model + +Status: Proposed canonical baseline + +## Scope and trust boundary + +Inkspan owns deterministic editor, conversion, canonical document-envelope, local revision/evidence, local autosave-ordering, accessibility metadata, and provider-neutral collaboration adapter behavior. A host owns network transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, audit storage, collaboration-provider lifecycle, and model-use policy. + +Protected `main` is the implementation authority. Open pull requests are evidence of proposed or active work only and must not be treated as shipped security controls until protected integration. + +## Protected assets + +- document bodies and versioned `document_envelope` values; +- tenant-confidential equality metadata such as local revisions and durable strong entity tags; +- deterministic conversion artifacts and release packages; +- local lifecycle, selection, transition, and collaboration metadata; +- host-supplied callbacks, provider bindings, and authorization context that Inkspan must not reinterpret; +- package/release provenance and exact-head verification evidence. + +Document bodies are content, not authorization. Revisions and strong validators are concurrency/equality evidence, not bearer credentials, signatures, tenant identifiers, or permission grants. + +## Threat actors and inputs + +Threats include malicious or malformed clipboard HTML, links, images, document envelopes, JSON/UTF-8 bytes, host callbacks, DOM capabilities, JavaScript proxies/accessors, form submissions, collaboration updates/awareness, Office-renderer input, package/release state, and compromised or misconfigured embedding hosts. Ordinary author mistakes and concurrent edits are treated as reliability threats when they can cause data loss or false durable-success claims. + +## Principal threat scenarios + +### Rich clipboard and active content + +Untrusted clipboard HTML can attempt script execution, external resource fetches, hidden-content smuggling, SVG/MathML or embedded active content, malformed tree reconstruction, unsafe links, resource exhaustion, or browser-parser differentials. The supported contract is fail-closed bounded semantic sanitization in the actual TipTap/ProseMirror paste pipeline. Cross-engine Chromium, Firefox, and WebKit differential evidence is a release-assurance requirement for the richer sanitizer line; deterministic jsdom evidence alone must not be represented as universal browser conformance. + +### Links, images, and external resources + +URLs or image-like content can exfiltrate document context, induce unexpected network access, or smuggle executable/active payloads. Inkspan validates only supported local semantics and does not grant network authority. Hosts remain responsible for downstream CSP, fetch policy, proxy/egress controls, content serving, and tenant authorization. + +### Spreadsheet formula injection + +XLSX cell values beginning with formula-significant prefixes can become executable spreadsheet formulas when opened by a user. Deterministic Office rendering must preserve the documented formula-injection neutralization boundary and never silently convert untrusted strings into formulas. No macro, network, or Desktop Office execution is part of the renderer contract. + +### Malformed Office structures and publication races + +DOCX/XLSX/PPTX generation must reject unsupported or malformed structures, invalid XML 1.0 content, excessive nesting/container growth, invalid worksheet names, invalid freeze panes, and package-bound violations. File publication must be race-safe, deterministic, and explicit about overwrite behavior. A successful local build is not durable release publication authority. + +### SSR and native forms + +A hidden/native form field contains client-controlled submission data. It is not authentication, authorization, CSRF protection, tenant identity, integrity proof, or durable-write evidence. Server rendering must not construct the browser editor. Hosts must validate and authorize submitted values independently. + +### Revision, selection, transition, and autosave evidence + +Local SHA-256 revisions identify deterministic content equality only. Selection coordinates are structural positions bound to one exact editor state and are not durable cross-revision anchors. Transition evidence does not prove actor, time, authorization, or durable persistence. Autosave observers must emit only document-free lifecycle metadata; observer failures cannot alter ordering or save outcomes. Durable compare-and-swap requires a host/server-selected strong validator under RFC 9110 semantics and must not be replaced with a local content digest. + +### Concurrency and stale state + +Concurrent editors, delayed digests, stale selections, ambiguous transport failure, or stale durable validators can cause lost updates or false success. Inkspan must bind asynchronous evidence to one immutable local state, keep autosave single-flight with bounded pending work, fail closed on ambiguous durable outcomes, and require explicit recovery from blocked conflict/failure states. Hosts own atomic persistence transactions and durable conflict resolution. + +### Collaboration and Yjs + +Inkspan may bind to Yjs-compatible document/awareness surfaces but does not own provider creation, room authorization, tenant identity, persistence, retention, or durable audit. Yjs updates and awareness metadata can contain sensitive tenant information. Host providers must authenticate rooms, authorize membership, bound awareness disclosure, and apply retention/encryption policy. Inkspan must not silently create a network provider or elevate an awareness update into authorization. + +### Model-assisted authoring + +Model output is untrusted proposed content. Deterministic editor/conversion validation remains authoritative. Inkspan must not own or expose model credentials, route models, authorize external data use, or treat model output as approved durable content. Hosts own model policy, redaction, routing, logging, retention, user approval, and tenant disclosure decisions. + +### Release and supply chain + +Stale draft assets, digest mismatch, mutable dependency/workflow references, absent SBOM/provenance, package drift, or stale exact-head checks can produce unverifiable releases. Publication must fail closed on ambiguous artifact inventory or digest mismatch. Exact-head CI/security/package/provenance evidence does not transfer after source movement. Automated comments/statuses are not formal approval. + +## Security invariants + +1. No Inkspan code path acquires host transport, tenant, credential, durable-storage, or model-routing authority implicitly. +2. Untrusted document/clipboard/form/Office input is validated before it reaches privileged or durable boundaries. +3. Public failures are bounded and redacted; document bodies, secrets, private exception causes, and tenant values are not reflected into generic diagnostics. +4. Resource ceilings apply before expensive traversal, parsing, hashing, rendering, or packaging where practical. +5. Provider-neutral collaboration cannot create or destroy the host provider. +6. Lifecycle and evidence metadata remains document-free unless an explicit versioned contract says otherwise. +7. Deterministic conversion is separate from model-assisted authoring. +8. Release authority requires exact integrated protected-head evidence and repository policy, not local or predecessor evidence. + +## Verification and residual risk + +Verification uses exact owned production coverage, hostile-input regression tests, packed ESM/CommonJS/strict-TypeScript consumers, SSR tests, deterministic Office renderer tests, security scanning, package inspection, documentation contracts, and release evidence. Real-browser parser differential testing is required where the browser itself materially participates in security semantics. + +Residual risk remains in embedding-host policy, browser engine behavior, downstream renderers/viewers, provider implementations, host persistence/authorization, model providers, and deployment configuration. Those risks must be addressed by host controls rather than by expanding Inkspan authority. + +## Rollback + +A security feature that proves unsafe is removed or disabled at the narrow Inkspan boundary while preserving canonical document readability and host-owned durable state. Rollback must not rewrite tenant persistence, weaken host authorization, or reinterpret release evidence. Material security-boundary changes require an ADR and fresh exact-head verification. From 3982f5914055fa8879ff145a404233b098be2de9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:04:14 +0900 Subject: [PATCH 008/101] docs(test): define canonical Inkspan test strategy --- docs/TEST_STRATEGY.md | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 docs/TEST_STRATEGY.md diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md new file mode 100644 index 00000000..d310f528 --- /dev/null +++ b/docs/TEST_STRATEGY.md @@ -0,0 +1,75 @@ +# Inkspan Test Strategy + +Status: Proposed canonical baseline + +## Purpose + +Inkspan testing must prove deterministic authoring/conversion behavior, fail-closed security boundaries, package compatibility, accessibility semantics, and release evidence without conflating local correctness with host authorization or durable persistence. Protected `main` remains the implementation authority; open feature branches are not shipped evidence. + +## Test pyramid and evidence classes + +### Pure deterministic unit tests + +Exercise document-envelope validation, canonicalization, UTF-8 handling, revision derivation, transition evidence, selection capture, autosave queue/state transitions, link/image policy, clipboard reconstruction, conversion primitives, Office renderer validation, and error normalization. Inputs include hostile objects, proxies/accessors, malformed JSON/UTF-8, deep or large structures, invalid identifiers, and boundary values. + +### Component and integration tests + +Exercise TipTap/ProseMirror integration, actual paste-pipeline installation, SSR/hydration, native form serialization, provider-neutral Yjs bindings, editor lifecycle, autosave durable-session handoff, and deterministic conversion packages. Tests must use the actual public adapter path instead of invoking an unregistered configuration field or bypassing the integration layer. + +### Package-consumer tests + +Install or consume the packed artifacts rather than source-tree aliases. Verify ESM, CommonJS, and strict TypeScript consumers. Framework-independent subpaths must compile and run without accidental React, TipTap UI, ProseMirror view, Yjs, DOM, network, or credential dependencies when the public contract excludes them. + +### Browser differential tests + +Where browser fragment parsing or serialization participates in a security boundary, use dependency-locked Playwright coverage across Chromium, Firefox, and WebKit. The same adversarial corpus must run in all required engines. Differences are not normalized away merely to produce parity; every reviewed allowlisted difference requires a standards basis and threat analysis. Missing/skipped browsers are not successful release evidence. + +### Office artifact tests + +Exercise realistic DOCX, XLSX, and PPTX fixtures and inspect the generated package structure. Cover XML 1.0 validity, formula-injection neutralization, worksheet naming and freeze panes, bounds/depth/cycles, deterministic metadata, publication races, overwrite semantics, and wheel/package contents. No macro, network, model, or Desktop Office execution is required by the deterministic renderer. + +### Security and static analysis + +Run repository security scanning, Semgrep/SAST, dependency and supply-chain checks, secret scanning where configured, package/license inspection, immutable workflow/source checks, and hostile-input regressions. Scanner success does not replace behavioral tests. + +### Accessibility tests + +Verify native control semantics, focus behavior, `aria-pressed`, `aria-keyshortcuts`, keyboard parity, programmatic status data, SSR behavior, non-color status semantics, and host-facing lifecycle information. Automated checks supplement rather than replace manual assistive-technology and interaction review for a release candidate. + +## Coverage policy + +Owned production code targets exact 100% statement, branch, function, and line coverage where supported by the language/toolchain. Coverage is a structural completeness gate, not proof of semantic correctness. Tests must continue to include realistic domain and adversarial behavior instead of creating vacuous branches merely to satisfy a percentage. + +Office Python surfaces additionally require complete public docstrings and branch/statement coverage under the supported Python matrix. JavaScript/TypeScript public declarations and package boundaries require strict consumer compilation. + +## Security corpus + +At minimum, maintain regressions for: + +- duplicate JSON object names, negative zero, malformed JSON, malformed UTF-8, BOM, depth/value/string/byte limits, sparse/decorated/non-plain objects, symbols, accessors, proxies, reflection failures, and detached/cross-realm byte views; +- rich clipboard scripts, embeds, resources, forms, metadata, SVG/MathML, images, hidden subtrees, `dialog`, `details`, `popover`, Office `mso-hide`, CSS comments/escapes/case/whitespace, malformed fragments, tables/lists/formatting elements, unsafe links, and resource ceilings; +- SSR client-controlled form values, escaping, hydration continuity, reset behavior, and absence of server editor construction; +- autosave stale validators, conflict/failure recovery, ambiguous transport outcomes, duplicate/no-op lifecycle transitions, callback exceptions, queue bounds, flush/close behavior, and durable-validator coherence; +- selection/revision races and document movement during asynchronous hashing; +- Office formula prefixes, invalid XML characters, malicious strings, path/publication races, invalid worksheet names, invalid freeze panes, cyclic input, pathological nesting, excessive container size, and partial write failure; +- package/release stale draft assets, unexpected local entries, digest mismatch, stale exact-head evidence, mutable provenance inputs, and isolated packed-consumer behavior. + +## Concurrency and failure testing + +Use deterministic barriers/fakes for local concurrency and real process/file boundaries where required. Prove that an observer exception cannot alter queue ordering; a stale digest cannot bind to a later editor state; an ambiguous durable save does not advance a validator; close/recovery does not leak waiters; and file publication either completes under the documented contract or fails without silently replacing unrelated content. + +Host persistence transactions, tenant isolation, distributed collaboration authorization, durable audit storage, and production network retry policy are host-owned and must be tested by the embedding product. Inkspan tests verify only the explicit adapter contract at those boundaries. + +## Release acceptance + +A release candidate requires the exact integrated protected head to satisfy applicable CI, security, 100% owned production coverage, public-docstring, package-consumer, accessibility, browser differential, Office artifact, SBOM/provenance, reproducibility, unresolved-thread, independent-review, and release-workflow gates. Queued, skipped-required, cancelled, absent, stale-head, predecessor-head, status-only, or synthetic-merge evidence is not accepted as success. + +The 0.6.0 rich-clipboard release line specifically requires the Chromium, Firefox, and WebKit differential gate before publication. Deterministic jsdom coverage remains useful but is not a substitute for browser-engine acceptance. + +## Documentation verification + +Documentation tests must compare canonical PRD/TRD/Architecture/ADR/UML/data-model/security/operability claims against current public package names, state enums, runtime versions, integration boundaries, and release evidence. They should reject obsolete product/internal names and unsupported claims, not merely check that files exist. + +## Rollback of a test gate + +A gate may be changed only because its product contract changed or the gate itself is technically invalid. The replacement begins with a regression that demonstrates the mismatch. Do not disable, skip, broaden allowlists, or lower coverage/security thresholds merely to make a branch green. From 537d31555bf32232684a9fdefdd5e7ff4f0c398a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:04:47 +0900 Subject: [PATCH 009/101] docs(ops): define Inkspan operability and recovery --- docs/OPERABILITY.md | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 docs/OPERABILITY.md diff --git a/docs/OPERABILITY.md b/docs/OPERABILITY.md new file mode 100644 index 00000000..1232c21d --- /dev/null +++ b/docs/OPERABILITY.md @@ -0,0 +1,95 @@ +# Inkspan Operability and Recovery + +Status: Proposed canonical baseline + +## Operational model + +Inkspan is a library/product module, not a host control plane. It owns deterministic editor, conversion, evidence, local autosave ordering, package, and provider-neutral adapter behavior. A host owns network transport, authentication, authorization, tenant isolation, persistence, credentials, migrations, retention, deployment, durable audit storage, collaboration-provider lifecycle, and model-use policy. + +This distinction controls incident ownership: an Inkspan incident is a deterministic package/editor/conversion/evidence defect or a violated public boundary. A host outage, database failure, provider outage, tenant authorization failure, or model-provider failure is a host incident unless Inkspan caused or amplified it through an explicit adapter contract. + +Protected `main` is the shipped implementation authority. Open PRs are not operational authority until protected integration. + +## Health and evidence + +Inkspan itself does not expose a network health endpoint. Operational health is proven through exact-head CI and package-consumer evidence, deterministic runtime outcomes, bounded public errors, security scans, package/release verification, and host-observable local state. + +Hosts may derive UI or local telemetry from document-free lifecycle snapshots, but must not expose document bodies, revision/entity tags, provider metadata, tenant identifiers, prompts, or model outputs as public metric dimensions or unauthenticated logs. High-cardinality tenant-confidential equality metadata remains local/private unless a host policy explicitly authorizes sharing. + +## Autosave operations + +The local autosave queue is single-flight with bounded pending work. Durable sessions use a host/server-selected strong HTTP entity tag for compare-and-swap. A local SHA-256 document revision is not a durable validator. + +Operational states are `idle`, `saving`, `blocked`, `closing`, and `closed`. Blocked conflict or ambiguous failure requires explicit recovery. No-op lifecycle operations do not manufacture synthetic state changes. Observer exceptions are presentation/telemetry failures and must not change persistence ordering. + +Host operators should treat: + +- conflict as a durable concurrency event requiring authenticated compare/merge/fork/reload policy; +- ambiguous transport failure as unknown durable state until the host proves the result; +- malformed or missing strong validators as a fail-closed host integration defect; +- repeated blocked state as a host-visible error requiring user/operator recovery rather than automatic silent retries. + +## Collaboration operations + +The host creates, authorizes, monitors, and destroys the Yjs-compatible provider. Inkspan must not own provider credentials, reconnect policy, room authorization, awareness retention, tenant admission, or durable update storage. When the provider is unavailable, the embedding host decides whether local editing remains available, becomes read-only, or blocks. Inkspan does not invent durable collaboration success. + +## Deterministic conversion operations + +Markdown/HTML/editor conversion and Office rendering are deterministic local operations. Office rendering runs without model, external network, macro, or Desktop Office authority. Inputs are bounded and validated before publication. On validation or publication failure, the operation fails with bounded diagnostics; operators must not reuse a partial artifact as successful output. + +File publication must follow the documented atomic/non-overwrite behavior. A caller-requested overwrite remains explicit. A failed write or validation does not authorize cleanup of unrelated host files. + +## Release operations + +Release publication occurs only from an exact integrated protected head. Release evidence includes package artifacts, deterministic checksums, CI/security/package/provenance results, required review, zero valid unresolved findings, and repository-policy acceptance. + +Before publication: + +1. build the exact expected artifact inventory; +2. verify local entries and digests; +3. verify any resumed remote draft has exactly the expected uploaded asset names and digests; +4. fail closed on stale/unexpected/incomplete assets rather than deleting them automatically; +5. verify SBOM/provenance/signing or attestation gates where configured; +6. verify package/wheel consumers and supported runtime matrix; +7. publish only after exact-head required review and protection gates pass. + +After publication, verify artifact availability, checksums/provenance, package metadata, install/consumer smoke evidence, and release notes. Rollback of a bad release uses a new reviewed corrective release or repository-supported withdrawal/yank policy; immutable published evidence is not rewritten to pretend the release never existed. + +## Incident classes and first response + +### Security input bypass + +Stop publication of affected versions, reproduce on exact source, preserve a minimized synthetic regression, classify whether the defect is inside Inkspan or host policy, patch test-first, rerun security/package/release evidence, and follow `SECURITY.md` disclosure handling once it is protected-main authority. Do not publish proof-of-concept customer data. + +### Data-loss or false durable-success risk + +Fail closed. Preserve the host's last known durable validator and local evidence. Do not mark an ambiguous write as saved. Require authenticated host reconciliation before resuming. Never substitute a content digest for server durable state. + +### Package or conversion corruption + +Do not publish or reuse the artifact. Rebuild from exact source with deterministic dependencies, verify the package tree and digest, and compare to the known-good contract. If a published artifact is affected, use the release recovery procedure rather than silently replacing immutable evidence. + +### Browser/parser divergence + +When a browser-specific clipboard/security difference is found, add it to the cross-engine corpus. Accept a difference only with explicit standards basis and threat analysis. Do not normalize a security-relevant difference away solely to regain parity. + +### Dependency or workflow incident + +Treat central `.github` or other dedicated-loop defects as read-only dependencies. Do not create an Inkspan workaround that weakens exact-head evidence, coverage, security, approval, or release policy. Continue independent Inkspan work that does not rely on the defective dependency. + +## Backup, migration, and retention + +Inkspan owns no application database on the current architecture, so database backup/restore and tenant retention are host responsibilities. Versioned document envelopes and public package schemas must remain backward/migration-aware; host migration implementation and schema registry remain host-owned. If Inkspan later owns durable persistence, that is a material architecture change requiring a physical ERD, migration/rollback design, backup/restore runbook, retention model, threat review, and ADR. + +## Rollback + +Rollback is boundary-specific: + +- editor feature: remove or revert the feature while preserving canonical document readability; +- autosave/observer feature: fall back to explicit `getSnapshot()`/host coordination without rewriting durable state; +- collaboration adapter: detach the adapter without destroying the host provider or Yjs document; +- Office renderer change: revert the deterministic renderer behavior and rebuild artifacts; do not modify host files outside the explicit output target; +- documentation: supersede inaccurate decisions with an ADR and synchronized canonical docs rather than deleting history; +- release: issue a verified corrective release or supported withdrawal action; preserve provenance and incident evidence. + +Every rollback requires fresh exact-head tests and must not weaken authorization, tenant isolation, release provenance, or host ownership boundaries. From d8be3e27a50ed1bcac242d4d4c3bf6868451c1a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:05:24 +0900 Subject: [PATCH 010/101] docs(trace): add standards and evidence traceability --- docs/TRACEABILITY.md | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/TRACEABILITY.md diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md new file mode 100644 index 00000000..6f69c16c --- /dev/null +++ b/docs/TRACEABILITY.md @@ -0,0 +1,71 @@ +# Inkspan Standards and Evidence Traceability + +Status: Proposed canonical baseline + +## Purpose + +This record maps durable Inkspan product decisions to authoritative standards, primary technical documentation, repository evidence, and explicit claim limits. It is not a certification statement. Protected `main` remains the implementation authority; open pull requests are proposed or active evidence only. + +## Traceability matrix + +| Concern | Inkspan decision | Primary authority | Repository evidence | Claim limit | +|---|---|---|---|---| +| HTTP optimistic concurrency | Durable saves use a host/server-selected strong entity tag; local content digests do not substitute for durable `If-Match` authority | RFC 9110, HTTP Semantics | autosave session tests, `docs/document-autosave.md`, architecture concurrency sequence | Inkspan validates/coordinates local semantics; host owns atomic persistence and authorization | +| JSON envelope grammar | Versioned envelopes use strict JSON handling, duplicate-name defenses, bounded parsing, and explicit schema identity | RFC 8259, JSON | envelope parser/resource-limit tests and package consumers | Current-schema parsing does not imply migration authority for unknown schemas | +| Canonical document bytes | Deterministic revision evidence is derived from canonicalized validated document content | RFC 8785, JSON Canonicalization Scheme | revision-evidence, transition-evidence, restore tests | A content digest proves equality only, not actor/time/authorization/durable write | +| Provenance semantics | Local transition/release evidence keeps content lineage separate from actor/authorization/durable claims | W3C PROV family | transition evidence, release evidence, canonical data model | Inkspan does not claim complete PROV conformance or host audit provenance | +| Accessibility | Native controls, keyboard semantics, shortcut metadata, and host-facing status state support accessible embedding | W3C WCAG 2.2; WAI-ARIA where used | toolbar/accessibility tests, SSR tests, autosave lifecycle data | Component evidence alone is not a full host WCAG conformance claim | +| Browser clipboard behavior | Security-relevant rich HTML handling requires actual paste-pipeline integration and real-engine differential evidence before the rich-clipboard release line | WHATWG HTML parsing; W3C Clipboard API; Playwright browser/project documentation | rich-clipboard unit/integration corpus and planned Chromium/Firefox/WebKit gate | jsdom-only success is not universal browser-engine conformance | +| Editor integration | Public behavior must exercise the actual TipTap/ProseMirror integration path, not an inert extension field or test-only hook | official TipTap and ProseMirror documentation for the locked dependency line | integration tests and package consumers | Inkspan does not claim compatibility with untested major-version integration semantics | +| Collaboration | Inkspan provides provider-neutral editor/Yjs bindings; host owns provider lifecycle, room authorization, awareness privacy, persistence and audit | official Yjs/provider documentation plus Inkspan public contract | collaboration tests and architecture ownership matrix | No network-provider or tenant-authorization authority is implied | +| Secure development | Security controls are developed test-first, with exact-head scanning/review/package evidence and root-cause regression | NIST SP 800-218 SSDF 1.1 | CI/security/SAST/package/provenance gates, doctoring and regression history | Repository evidence is not a claim of complete SSDF organizational conformance | +| Office rendering | JSON→DOCX/XLSX/PPTX is deterministic, bounded, network-free, macro-free, injection-aware and package-inspected | Office Open XML specifications and relevant Python package contracts | Office renderer tests, Python coverage/docstring/package gates | Format fidelity is limited to explicitly tested supported constructs | +| Release authority | Source movement invalidates exact-head evidence; stale assets/digest ambiguity fail closed; formal approval remains distinct from status/comments | GitHub protected-branch/review/release/attestation behavior and repository policy | release workflow tests, package checksums, SBOM/provenance, formal reviews | Local success or automated prose does not authorize protected merge/release | + +## Current primary references + +Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) Data Interchange Format* (RFC 8259; STD 90). RFC Editor. https://doi.org/10.17487/RFC8259 + +Fielding, R., Nottingham, M., & Reschke, J. (Eds.). (2022). *HTTP Semantics* (RFC 9110; STD 97). RFC Editor. https://doi.org/10.17487/RFC9110 + +Rundgren, A., Jordan, B., & Erdtman, S. (2020). *JSON Canonicalization Scheme (JCS)* (RFC 8785). RFC Editor. https://doi.org/10.17487/RFC8785 + +Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure Software Development Framework (SSDF) Version 1.1: Recommendations for Mitigating the Risk of Software Vulnerabilities* (NIST SP 800-218). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218 + +World Wide Web Consortium. (2024, December 12). *Web Content Accessibility Guidelines (WCAG) 2.2*. https://www.w3.org/TR/WCAG22/ + +World Wide Web Consortium. (2013). *PROV-DM: The PROV Data Model*. https://www.w3.org/TR/prov-dm/ + +Microsoft. (n.d.). *Browsers*. Playwright documentation. https://playwright.dev/docs/browsers + +Microsoft. (n.d.). *Projects*. Playwright documentation. https://playwright.dev/docs/test-projects + +## Research-backed concurrency rationale + +The autosave design uses explicit optimistic-concurrency boundaries: Inkspan coordinates local single-flight work and immutable local evidence, while the host performs the authoritative atomic compare-and-swap. The classic optimistic-concurrency literature is rationale, not protocol authority: + +Kung, H. T., & Robinson, J. T. (1981). On optimistic methods for concurrency control. *ACM Transactions on Database Systems, 6*(2), 213–226. https://doi.org/10.1145/319566.319567 + +## Evidence hierarchy + +1. Protected `main` source and versioned public contracts. +2. Exact-current-head CI/security/package/provenance evidence for the source being considered. +3. Formal current-head review and repository protection state. +4. Canonical PRD/TRD/Architecture/ADRs/UML/data model/security/test/operability documents synchronized to that source. +5. Feature doctoring and implementation plans. +6. Historical PR bodies, predecessor-head results, conversations, comments, and local-only evidence. + +Lower levels may explain intent or history but cannot override a contradictory higher-level source. + +## Status discipline + +- **Implemented** means present in protected `main` and verified under its release/product contract. +- **Proposed** means documented or implemented on an unmerged branch and not yet protected-main authority. +- **Planned** means an accepted future direction without a protected implementation. +- **Superseded** means retained for history but replaced by a later explicit decision. + +Documentation must not promote Proposed or Planned capabilities to Implemented merely because a PR, issue, or design document is detailed. + +## Review cadence + +Revalidate this matrix when a public schema, security boundary, supported runtime/browser line, Office format contract, collaboration/provider contract, accessibility interaction, release workflow, or authoritative external standard materially changes. Prefer explicit supersession over silent historical rewrite. From 900550c6f7cadd3ab5bbd48bd90183040f718722 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:05:39 +0900 Subject: [PATCH 011/101] docs(adr): record product and host authority boundary --- docs/adr/0001-product-host-authority.md | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0001-product-host-authority.md diff --git a/docs/adr/0001-product-host-authority.md b/docs/adr/0001-product-host-authority.md new file mode 100644 index 00000000..115c647f --- /dev/null +++ b/docs/adr/0001-product-host-authority.md @@ -0,0 +1,27 @@ +# ADR 0001: Product and host authority boundary + +Status: Proposed + +## Context + +Inkspan must work as a standalone authoring/conversion product and as a module inside naruon or another CWL host. Mixing host transport, tenant, identity, persistence, credential, deployment, retention, audit, or model-routing authority into the editor package would make standalone use harder and create hidden security coupling. + +## Decision + +Inkspan owns deterministic editor, conversion, canonical envelope, local evidence, local autosave ordering, accessibility metadata, package, and provider-neutral adapter behavior. Hosts own transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, durable audit storage, collaboration-provider lifecycle, and model-use policy. + +## Consequences + +The same package can be embedded or used independently. Host failures remain explicit adapter failures rather than becoming implicit editor state. Some end-to-end properties, such as tenant authorization and durable atomic writes, cannot be proven by Inkspan alone and require host verification. + +## Failure and recovery + +If an Inkspan change begins to create network providers, choose tenants, store secrets, authorize model calls, or claim durable persistence success, fail the architecture contract and revert the authority expansion. Host integration defects are repaired at the host boundary rather than by granting Inkspan broader privilege. + +## Verification + +Canonical Architecture/PRD/TRD ownership language, integration tests, package-consumer isolation, provider-neutral collaboration tests, and documentation contracts must agree. Protected `main` remains the implementation authority. + +## Rollback or supersession + +Rollback removes the authority-expanding path while preserving deterministic document compatibility. Supersession requires a material architecture proposal with threat model, migration/rollback, deployment, and tenant-ownership evidence. From faa2ce4164de0017159f7d8ee35507da59052bc4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:05:58 +0900 Subject: [PATCH 012/101] docs(adr): record document and revision authority --- docs/adr/0002-document-revision-authority.md | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0002-document-revision-authority.md diff --git a/docs/adr/0002-document-revision-authority.md b/docs/adr/0002-document-revision-authority.md new file mode 100644 index 00000000..2d6b5b0c --- /dev/null +++ b/docs/adr/0002-document-revision-authority.md @@ -0,0 +1,27 @@ +# ADR 0002: Canonical document and revision authority + +Status: Proposed + +## Context + +Inkspan needs deterministic document persistence/export and local equality evidence without turning a content digest into authorization, identity, or durable concurrency authority. + +## Decision + +A versioned validated `document_envelope` is the canonical document value. Strict JSON/UTF-8 handling and bounded validation precede canonicalization. SHA-256 revision evidence is derived from the exact canonical envelope and is equality evidence only. Durable compare-and-swap uses a host/server-selected strong validator under RFC 9110 semantics. + +## Consequences + +Local restore, transition, and selection evidence can bind to exact content without copying document bodies. Hosts must maintain their own durable version, actor, authorization, audit, migration, and retention semantics. Unsupported envelope versions remain explicit migration routes rather than permissive parsing. + +## Failure and recovery + +Malformed, ambiguous, over-limit, unsupported, or hostile envelope input fails closed with bounded diagnostics. If local state moves during asynchronous evidence capture, the operation returns no stale claim. Durable ambiguity is reconciled by the host; a local digest never advances durable state. + +## Verification + +Envelope parsing/canonicalization/UTF-8/resource-limit regressions, revision/transition/selection tests, packed consumer tests, and RFC 9110/JCS documentation must remain coherent. + +## Rollback or supersession + +A future algorithm/schema change adds a versioned contract and migration path. It must not silently redefine existing revision values. Supersession requires compatibility tests, rollback, and updated traceability. From e46fe8e52924457dbb7aa1906504261b384778f8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:07:22 +0900 Subject: [PATCH 013/101] docs(adr): record safe rich clipboard boundary --- docs/adr/0003-safe-rich-clipboard.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0003-safe-rich-clipboard.md diff --git a/docs/adr/0003-safe-rich-clipboard.md b/docs/adr/0003-safe-rich-clipboard.md new file mode 100644 index 00000000..d9b928db --- /dev/null +++ b/docs/adr/0003-safe-rich-clipboard.md @@ -0,0 +1,27 @@ +# ADR 0003: Safe rich clipboard boundary + +Status: Proposed + +## Context + +Rich clipboard HTML is attacker-controlled browser input. A sanitizer that is correct only as a pure helper but is not installed in the real TipTap/ProseMirror paste pipeline does not protect the product. Browser fragment parsing can also differ across Chromium, Firefox, and WebKit. + +## Decision + +Sanitize untrusted rich HTML through a bounded, fail-closed semantic allowlist installed in the actual TipTap/ProseMirror paste pipeline. The sanitizer performs no external fetch or active execution, rejects unsupported active/resource-bearing structures, applies resource ceilings, and keeps its pure API behavior aligned with editor integration. Browser-engine differential evidence is required before the rich-clipboard release line is published. + +## Consequences + +Supported semantic formatting can survive paste while active or hidden content is removed or rejected. A downstream host still owns CSP, network egress, rendering policy, tenant authorization, and any later transforms. Cross-engine tests increase release cost but reduce parser-specific acquisition risk. + +## Failure and recovery + +Malformed input, hostile DOM capabilities, reflection failures, over-limit input, or unsafe structures fail closed with bounded diagnostics. If a security-relevant engine difference is found, add it to the differential corpus and repair the sanitizer or explicitly document a standards-grounded safe difference. Do not broaden the allowlist merely to recover parity. + +## Verification + +Use sanitizer unit tests, actual editor paste-pipeline integration tests, hostile DOM/reflection cases, package consumers, security scans, and the dependency-locked Chromium/Firefox/WebKit differential release gate tracked by the rich-clipboard assurance issue. + +## Rollback or supersession + +Rollback disables the rich transform or reverts to a narrower safe input path without granting arbitrary HTML authority. Supersession requires an equivalent or stronger fail-closed browser-integrated boundary, threat analysis, and fresh cross-engine evidence. From 494eef73930bafee11ade4c4c427ab81d392f5d7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:07:37 +0900 Subject: [PATCH 014/101] docs(adr): record durable validator autosave boundary --- docs/adr/0004-durable-validator-autosave.md | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0004-durable-validator-autosave.md diff --git a/docs/adr/0004-durable-validator-autosave.md b/docs/adr/0004-durable-validator-autosave.md new file mode 100644 index 00000000..1eeca01e --- /dev/null +++ b/docs/adr/0004-durable-validator-autosave.md @@ -0,0 +1,27 @@ +# ADR 0004: Strong durable validator and bounded autosave + +Status: Proposed + +## Context + +Local editor revisions are useful equality evidence but cannot prove a durable server write. Autosave also must avoid concurrent duplicate writes, unbounded queued work, silent conflict recovery, and telemetry callbacks that alter persistence behavior. + +## Decision + +Use a single-flight autosave queue with bounded active/pending work and explicit `idle`, `saving`, `blocked`, `closing`, and `closed` lifecycle state. A durable session accepts and advances only host/server-selected strong HTTP entity tags for compare-and-swap. Conflict or ambiguous save failure blocks progression until explicit recovery. Optional lifecycle observation emits only distinct document-free transitions; construction and no-op operations emit nothing, and observer exceptions are isolated. + +## Consequences + +Inkspan can coordinate deterministic local ordering while the host remains the only durable authority. Hosts must implement atomic `If-Match` semantics, authorization, retry policy, and durable reconciliation. UI can observe bounded machine state without polling or receiving document bodies. + +## Failure and recovery + +Malformed or weak validators fail closed. Conflict preserves durable uncertainty and requires authenticated host recovery. Ambiguous transport failure never advances the validator. Recovery with no pending work may return to idle; unsuccessful/no-op recovery does not synthesize an observer event. Closing waits only for bounded retained work. + +## Verification + +Queue/session state-machine tests, no-op observation regressions, callback-failure isolation, validator grammar tests, concurrency/flush/close regressions, packed ESM/CommonJS/strict-TypeScript consumers, and exact-head coverage/security gates verify the contract. + +## Rollback or supersession + +Rollback removes optional lifecycle observation or durable-session convenience while preserving explicit `getSnapshot()`, local queue ordering, and host-owned durable writes. Supersession requires an equally bounded concurrency model, exact validator semantics, migration/rollback, and fresh package-consumer evidence. From 78483163bb9ff982bb79ec3a55148ef3883dd261 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:07:55 +0900 Subject: [PATCH 015/101] docs(adr): record revision-scoped review evidence --- .../0005-revision-scoped-review-evidence.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0005-revision-scoped-review-evidence.md diff --git a/docs/adr/0005-revision-scoped-review-evidence.md b/docs/adr/0005-revision-scoped-review-evidence.md new file mode 100644 index 00000000..9abc5605 --- /dev/null +++ b/docs/adr/0005-revision-scoped-review-evidence.md @@ -0,0 +1,27 @@ +# ADR 0005: Revision-scoped review evidence + +Status: Proposed + +## Context + +Delayed review, annotation, AI assistance, and audit-like workflows need to refer to an exact editor state. Copying selected text or entire document bodies into ordinary metadata increases privacy exposure, while asynchronous hashing can accidentally bind coordinates to a later document if state is reread. + +## Decision + +Capture selection coordinates and the canonical document envelope from the same immutable editor state before asynchronous revision derivation. Transition evidence validates previous and resulting envelopes before deriving both revisions. Evidence contains only the minimum revision/coordinate/change metadata required by the versioned contract and excludes document bodies, actor, tenant, time, authorization, model identity, transport result, signature, and durable-write claims. + +## Consequences + +Hosts can detect stale review coordinates and content transitions without duplicating full document content in routine evidence. Hosts remain responsible for durable annotation IDs, cross-revision re-anchoring, actor/time attribution, authorization, audit storage, and model-use policy. + +## Failure and recovery + +If editor state changes during a capture boundary, the API must not emit a stale mixed-state claim. Coordinates are valid only with the matching revision. A changed document requires an explicit host re-anchor, compare, merge, fork, or collaborative anchoring policy. + +## Verification + +Use concurrency tests, range/caret cases, transition ordering tests, recursive document-content absence checks, frozen-output checks, packed ESM/CommonJS/strict-TypeScript consumers, and exact-head coverage/security gates. + +## Rollback or supersession + +Rollback removes the convenience evidence surface while preserving canonical envelope/revision primitives. Supersession requires a versioned anchor/evidence contract that retains minimum disclosure and explicitly defines compatibility/migration semantics. From df0a4f324da66e1f343415f49e64a025b531138c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:08:08 +0900 Subject: [PATCH 016/101] docs(adr): record SSR and native form boundary --- docs/adr/0006-ssr-native-form-boundary.md | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0006-ssr-native-form-boundary.md diff --git a/docs/adr/0006-ssr-native-form-boundary.md b/docs/adr/0006-ssr-native-form-boundary.md new file mode 100644 index 00000000..9a59fef0 --- /dev/null +++ b/docs/adr/0006-ssr-native-form-boundary.md @@ -0,0 +1,27 @@ +# ADR 0006: SSR and native form client-controlled boundary + +Status: Proposed + +## Context + +Inkspan must support server-rendered shells and optional native form integration without instantiating a browser editor on the server or treating a hidden field as trusted server state. Hydration must not lose the chosen initial value, and form serialization must stay synchronized once the editor becomes authoritative. + +## Decision + +Server rendering never constructs a TipTap/ProseMirror editor view. When `formFieldName` is explicitly enabled, Inkspan emits the selected controlled Markdown/HTML serialization as an escaped read-only native input value through SSR and matching hydration. Once the editor is authoritative, document transactions synchronously mirror the current serialization into the native field. The submitted value is client-controlled input only. + +## Consequences + +SSR hosts can participate in native form flows while preserving hydration continuity. Hosts remain responsible for authentication, authorization, CSRF defenses, tenant isolation, request validation/limits, durable concurrency, persistence, and acceptance. Hosts that cannot place a document body in server HTML must not enable this field. + +## Failure and recovery + +Invalid or stale client values never become authorization or durable evidence. Native resets cannot silently desynchronize a configured field from an editor the host intentionally retains. If SSR/form integration proves unsafe for a host, omit the field and use an explicit host transport after independent server validation. + +## Verification + +Use `renderToString`/SSR tests, controlled-over-default precedence, escaping cases, hydration continuity, synchronous transaction-to-`FormData` tests, reset behavior, opt-out non-disclosure, no server editor construction, and documentation contracts. + +## Rollback or supersession + +Rollback disables `formFieldName` or returns the host to explicit client transport without changing canonical document semantics. Supersession requires equivalent SSR safety, client-controlled-input treatment, compatibility tests, and a migration/rollback note. From a0d1e2640568a95debeb87561e6cea8fa4d9d6eb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:08:21 +0900 Subject: [PATCH 017/101] docs(adr): record provider-neutral collaboration boundary --- .../0007-provider-neutral-collaboration.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0007-provider-neutral-collaboration.md diff --git a/docs/adr/0007-provider-neutral-collaboration.md b/docs/adr/0007-provider-neutral-collaboration.md new file mode 100644 index 00000000..8831701f --- /dev/null +++ b/docs/adr/0007-provider-neutral-collaboration.md @@ -0,0 +1,27 @@ +# ADR 0007: Provider-neutral collaboration and host ownership + +Status: Proposed + +## Context + +Inkspan needs collaborative editing compatibility without choosing a network provider, room identity, tenant authority, credential, persistence store, retention policy, or audit system. Coupling those responsibilities to the editor would make standalone operation weaker and create hidden privilege. + +## Decision + +Inkspan may bind editor state to host-supplied Yjs-compatible document and awareness surfaces. The host creates, authenticates, authorizes, monitors, reconnects, persists, expires, and destroys the collaboration provider. Inkspan does not create or destroy that provider and does not interpret awareness or update receipt as authorization or durable persistence evidence. + +## Consequences + +Standalone and enterprise hosts can select their own collaboration transport and deployment model. Provider lifecycle and tenant security remain testable in the host rather than buried in the editor. Inkspan must keep its collaboration adapter narrow and must tolerate provider-independent mounting/unmounting. + +## Failure and recovery + +Provider outage, authorization failure, room loss, or awareness-policy failure is surfaced to the host. The host decides whether the editor remains locally writable, becomes read-only, reconnects, forks, or blocks. Detaching Inkspan must not destroy a provider shared with other product surfaces or erase the host-owned Yjs document. + +## Verification + +Use provider-neutral integration tests with supplied Yjs state, lifecycle/remount tests, awareness non-authority/privacy contracts, package-dependency checks, and architecture documentation tests. No test should require a production provider credential or network connection to prove the adapter contract. + +## Rollback or supersession + +Rollback detaches the collaboration adapter while preserving local document operation and the host-owned Yjs state/provider. Supersession requires an explicit versioned collaboration contract with equivalent host authority separation, migration/rollback, privacy, and operability evidence. From a660358140f24c297a0335238e2feb260e6ee7de Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:08:34 +0900 Subject: [PATCH 018/101] docs(adr): record deterministic Office rendering boundary --- .../0008-deterministic-office-rendering.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0008-deterministic-office-rendering.md diff --git a/docs/adr/0008-deterministic-office-rendering.md b/docs/adr/0008-deterministic-office-rendering.md new file mode 100644 index 00000000..e0fea8ff --- /dev/null +++ b/docs/adr/0008-deterministic-office-rendering.md @@ -0,0 +1,27 @@ +# ADR 0008: Deterministic Office rendering boundary + +Status: Proposed + +## Context + +Enterprise buyers need DOCX, XLSX, and PPTX output that is reproducible and testable without model inference, Desktop Office automation, macros, or hidden network access. Office formats also introduce formula injection, XML/package validity, resource exhaustion, and file-publication hazards. + +## Decision + +The Office renderer consumes a strict versioned JSON-compatible contract and produces deterministic DOCX/XLSX/PPTX artifacts locally. It is network-free, macro-free, model-free, and Desktop-Office-free. Validate XML 1.0 content, resource/container/depth limits, worksheet names, freeze panes, supported structures, and spreadsheet formula-injection boundaries before successful publication. Output publication is race-safe with explicit overwrite semantics. + +## Consequences + +Rendering remains independently deployable and auditable. Fidelity claims are limited to tested supported constructs rather than broad Office compatibility claims. Hosts retain storage, authorization, content classification, retention, and downstream viewer policy. + +## Failure and recovery + +Invalid or unsupported input fails closed with bounded diagnostics. Partial or failed output is not successful evidence and must not replace unrelated files. A caller requesting overwrite does so explicitly. Recovery rebuilds from the exact validated source rather than editing a partially generated package. + +## Verification + +Run supported Python-version tests, exact statement/branch coverage, complete public docstrings, realistic DOCX/XLSX/PPTX package inspection, formula-prefix regressions, XML-invalid character cases, cyclic/depth/container limits, worksheet/freeze-pane cases, publication-race tests, wheel/package inspection, license checks, and deterministic digest/evidence checks where applicable. + +## Rollback or supersession + +Rollback restores the last verified renderer contract and rebuilds artifacts without mutating host files outside the explicit target. Supersession requires a versioned input/output contract, migration/fidelity analysis, equivalent no-network/no-macro guarantees, and fresh package/release evidence. From 897e824b2c26b69251ead72247c593f11e08e3c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:08:56 +0900 Subject: [PATCH 019/101] docs(adr): record naruon modular composition --- docs/adr/0009-naruon-modular-composition.md | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0009-naruon-modular-composition.md diff --git a/docs/adr/0009-naruon-modular-composition.md b/docs/adr/0009-naruon-modular-composition.md new file mode 100644 index 00000000..0e4a6f14 --- /dev/null +++ b/docs/adr/0009-naruon-modular-composition.md @@ -0,0 +1,27 @@ +# ADR 0009: Naruon modular composition without product coupling + +Status: Proposed + +## Context + +CWL hosts need to compose Inkspan through naruon `compose` / `ui.panel` surfaces while standalone adopters must not acquire a naruon or contextual-orchestrator dependency. SSR, autosave, collaboration, model use, and durable storage also have distinct authority boundaries that must not collapse inside a panel component. + +## Decision + +Naruon integration is additive and host-owned. A naruon host mounts Inkspan through a narrow client boundary, passes only serializable non-secret configuration, owns authenticated API calls and strong durable validators, owns Yjs provider lifecycle, and optionally routes model assistance through contextual-orchestrator under host policy. Inkspan retains deterministic editor/conversion/evidence authority and does not import host control-plane authority. + +## Consequences + +Inkspan remains independently usable and testable, while CWL products can share composition conventions. Cross-document remount identity, accessible conflict/recovery UX, and server-selected validators are explicit host responsibilities. Shared platform defects are fixed in their owning repository rather than duplicated in Inkspan. + +## Failure and recovery + +A host must issue a fresh editing-context identity when switching authorized documents so local queue/editor state cannot bleed across documents. Provider or model outages are host-degraded modes. A central `.github`, naruon, or contextual-orchestrator defect is treated as a read-only dependency; Inkspan continues independent work rather than weakening local safety gates. + +## Verification + +Use `ARCHITECTURE.md`, `docs/naruon-compose-ui-panel.md`, architecture documentation tests, SSR/client-boundary tests, autosave validator/recovery tests, host-provider lifecycle tests, and packed standalone consumers proving no required naruon/contextual-orchestrator dependency. + +## Rollback or supersession + +Rollback detaches the naruon adapter/guide while preserving standalone Inkspan APIs and host data. Supersession requires an explicit versioned host composition contract, compatibility/migration evidence, and preserved standalone operation. From 4f8b8f89a546e3ac510ae1f6e59d60d2fa64b771 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:09:12 +0900 Subject: [PATCH 020/101] docs(adr): record release evidence authority --- docs/adr/0010-release-evidence-authority.md | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/adr/0010-release-evidence-authority.md diff --git a/docs/adr/0010-release-evidence-authority.md b/docs/adr/0010-release-evidence-authority.md new file mode 100644 index 00000000..9c266e9a --- /dev/null +++ b/docs/adr/0010-release-evidence-authority.md @@ -0,0 +1,27 @@ +# ADR 0010: Release evidence authority + +Status: Proposed + +## Context + +Inkspan releases combine JavaScript/TypeScript packages, Office Python artifacts, checksums, SBOM/provenance, exact-head CI/security evidence, and repository review/protection state. Stale draft assets or predecessor-head checks can look healthy while referring to different source. + +## Decision + +Release authority exists only for one exact integrated protected head. The release process verifies the expected local and remote artifact inventory and digests, package-consumer evidence, supported runtime matrix, applicable security/coverage/accessibility gates, SBOM/provenance, unresolved review findings, formal review requirements, and repository protection. Stale, unexpected, incomplete, or digest-mismatched draft assets fail closed and are not silently deleted or reused. Comments, model prose, status-only signals, predecessor evidence, or author assertions are not substitutes for formal approval where policy requires it. + +## Consequences + +Publication is slower than a best-effort upload but produces acquisition-reviewable evidence tied to exact source. Re-running after a head change is intentional. Historical releases and failed drafts remain auditable instead of being rewritten to produce a cleaner story. + +## Failure and recovery + +If artifact inventory, digest, provenance, review, or exact-head evidence is ambiguous, stop publication. Repair the source or release workflow, regenerate evidence from the exact head, and resume only through a contract that proves the existing remote draft is exactly expected. A bad published release is corrected through a new verified release or supported withdrawal/yank process. + +## Verification + +Use release-workflow regressions, expected-asset/digest tests, package and wheel consumers, reproducibility checks, security/coverage gates, SBOM/provenance/attestation checks where configured, formal review inspection, and post-publication artifact/checksum smoke verification. + +## Rollback or supersession + +Rollback never falsifies or deletes historical evidence to imply the failed publication did not occur. Supersession requires a versioned release contract with at least equivalent exact-source binding, artifact integrity, provenance, review, and recovery guarantees. From e6b28b9c4a19f12ebe215f6dd5c330c7efcb07f1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:09:37 +0900 Subject: [PATCH 021/101] docs(adr): index detailed canonical decisions --- docs/adr/README.md | 65 ++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index 51211259..54f03c0d 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -2,53 +2,38 @@ Status values: Proposed, Accepted, Superseded. -This index records durable architectural decisions. Protected-main implementation is required before a feature-specific decision may be treated as shipped behavior. +This index records durable architectural decisions. Protected-main implementation is required before a feature-specific decision may be treated as shipped behavior. Detailed ADR files are authoritative for their decision; this index is authoritative for discovery and status. | ADR | Status | Decision | |---|---|---| -| 0001 | Proposed | Product and host authority boundary | -| 0002 | Proposed | Canonical document and revision evidence | -| 0003 | Proposed | Safe rich clipboard boundary | -| 0004 | Proposed | Strong durable validator and bounded autosave | -| 0005 | Proposed | Revision-scoped review evidence | -| 0006 | Proposed | SSR/native form client-controlled boundary | -| 0007 | Proposed | Provider-neutral collaboration ownership | -| 0008 | Proposed | Release evidence and independent governance | +| [0001](0001-product-host-authority.md) | Proposed | Product and host authority boundary | +| [0002](0002-document-revision-authority.md) | Proposed | Canonical document and revision authority | +| [0003](0003-safe-rich-clipboard.md) | Proposed | Safe rich clipboard boundary | +| [0004](0004-durable-validator-autosave.md) | Proposed | Strong durable validator and bounded autosave | +| [0005](0005-revision-scoped-review-evidence.md) | Proposed | Revision-scoped review evidence | +| [0006](0006-ssr-native-form-boundary.md) | Proposed | SSR/native form client-controlled boundary | +| [0007](0007-provider-neutral-collaboration.md) | Proposed | Provider-neutral collaboration and host ownership | +| [0008](0008-deterministic-office-rendering.md) | Proposed | Deterministic Office rendering boundary | +| [0009](0009-naruon-modular-composition.md) | Proposed | Naruon modular composition without product coupling | +| [0010](0010-release-evidence-authority.md) | Proposed | Release evidence authority | -## Decision summaries +## Decision discipline -### ADR-0001 Product and host authority boundary +- **Proposed**: documented or implemented on an unmerged branch; not protected-main authority. +- **Accepted**: integrated into protected `main` with the applicable verification evidence. +- **Superseded**: retained for historical traceability but explicitly replaced by a later ADR. -Inkspan owns editor, deterministic conversion and local coordination. Hosts own transport, authentication/authorization, tenancy, durable persistence, credentials, migration, retention, durable audit, deployment and model policy. Alternative rejected: an editor package that silently becomes the host platform. +An ADR cannot promote an unmerged feature to shipped behavior. When a decision changes materially, add or supersede an ADR rather than silently rewriting history. -### ADR-0002 Canonical document and revision evidence - -Validate a versioned document envelope before deterministic canonicalization and SHA-256 revision derivation. Revision tags are equality evidence, not identity or authorization. Alternative rejected: hashing arbitrary editor/JSON serialization. - -### ADR-0003 Safe rich clipboard boundary - -Treat rich HTML as untrusted and sanitize through a bounded fail-closed semantic policy installed in the actual ProseMirror paste path. Alternative rejected: UI-only/manual sanitizer calls that do not protect real paste behavior. - -### ADR-0004 Strong durable validator and bounded autosave - -Use bounded single-flight local autosave. A server-selected strong validator is host-owned compare-and-swap evidence and advances only on validated durable success. Lifecycle observation reports only real externally visible transitions; construction and no-op operations emit nothing. Alternative rejected: treating a local content digest as durable server concurrency authority or allowing polling/subscriber growth to become persistence control. - -### ADR-0005 Revision-scoped review evidence - -Selections and document transitions are bound to exact revisions while ordinary evidence omits document bodies. Alternative rejected: copying selected/document text into every evidence object or reusing structural coordinates across revisions without explicit re-anchoring. - -### ADR-0006 SSR/native form client-controlled boundary - -Optional native form serialization is escaped SSR/hydration data and synchronously mirrors editor transactions, but submitted values remain untrusted client input. Alternative rejected: treating hidden fields as authorization, integrity or CSRF evidence. - -### ADR-0007 Provider-neutral collaboration ownership - -Inkspan exposes collaboration adapters without owning provider transport, tenant authorization, identity, durable collaboration storage or audit. Alternative rejected: coupling the package to one provider or application database. - -### ADR-0008 Release evidence and independent governance +## ADR quality requirements -Exact-head CI/security/package/provenance evidence, formal independent review where required, and fail-closed release-asset verification are separate authorities. Comments, statuses and predecessor evidence do not become formal approval. Alternative rejected: publication or merge from stale/ambiguous evidence. +Every material ADR records: -## ADR quality requirements +1. context and the problem boundary; +2. the selected decision and rejected authority expansion or alternative where material; +3. consequences and ownership trade-offs; +4. failure and recovery semantics; +5. verification/acceptance evidence; and +6. rollback or explicit supersession conditions. -Material follow-up ADRs must record context, alternatives, decision, consequences, security/privacy impact, failure/recovery, acceptance tests, migration/rollback and supersession conditions. Detailed standalone ADR files should replace these summaries as decisions evolve; the index remains authoritative for status and discovery. +Security/privacy, compatibility, migration, accessibility, operability, and release implications belong in those sections when relevant. Canonical PRD, TRD, Architecture, UML, data/evidence model, threat model, test strategy, operability, and traceability documents must remain synchronized with Accepted decisions. From a6ad45a845bac845737069113db360940516435e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:11:37 +0900 Subject: [PATCH 022/101] docs(changelog): record canonical acquisition documentation --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7632ecb2..d3b67106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ## [Unreleased] ### Documentation +- Added a canonical acquisition documentation spine covering product requirements, technical requirements, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and ten linked architecture decision records without inventing Inkspan-owned persistence or host authority +- Added a machine-checkable canonical-documentation contract that keeps required files, ADR index links, browser-security evidence, standards references, rollback sections, and host-vs-Inkspan authority boundaries synchronized - Added an authoritative standalone and modular MSA architecture contract with reviewable deployment, optimistic-concurrency, data-ownership, security, and acquisition-evidence diagrams and tables - Added a beginner-readable naruon compose and ui.panel integration guide covering narrow client hydration, server-selected strong validators, accessible conflict handling, host-owned Yjs lifecycle, contextual-orchestrator boundaries, and local-versus-shareable evidence - Added an opaque editing-context remount for the complete editor and autosave example, latest-generation asynchronous capture ordering, encoded document path segments, redacted recovery status, and lazy state-owned session identity to prevent cross-document state reuse From a528f75c79c9a43095654240122acf953e4b71ad Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:14:22 +0900 Subject: [PATCH 023/101] test(docs): require conversation-complete product contracts --- src/canonicalProductDocumentation.test.ts | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index dcfdfca9..8fe9e181 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -51,6 +51,32 @@ describe('canonical product documentation graph', () => { expect(operability).toContain('rollback'); }); + it('preserves the durable product decisions from the canonical conversation', () => { + const prd = repositoryFile('docs/PRD.md'); + const trd = repositoryFile('docs/TRD.md'); + const uml = repositoryFile('docs/UML.md'); + const dataModel = repositoryFile('docs/DATA_MODEL.md'); + + for (const marker of ['Markdown', 'HTML', 'Office', 'naruon', 'provider-neutral']) { + expect(prd).toContain(marker); + } + for (const marker of ['network-free', 'macro-free', 'formula', 'Office']) { + expect(trd).toContain(marker); + } + for (const marker of ['Office', 'naruon', 'Yjs', 'file publication']) { + expect(uml).toContain(marker); + } + for (const marker of [ + 'conversion_request', + 'conversion_artifact', + 'render_warning', + 'host_capability', + 'audit_event', + ]) { + expect(dataModel).toContain(marker); + } + }); + it('documents realistic security, test, and release evidence boundaries', () => { const threatModel = repositoryFile('docs/THREAT_MODEL.md'); const testStrategy = repositoryFile('docs/TEST_STRATEGY.md'); From 872b468ff4f0964198f8683241f209f85c71f605 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:15:14 +0900 Subject: [PATCH 024/101] docs(product): complete canonical Inkspan product requirements --- docs/PRD.md | 126 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 33 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 98c06f1d..834c437e 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -2,58 +2,118 @@ Status: Proposed canonical baseline -## Product +## Product definition -Inkspan is a standalone rich-text authoring package and an embeddable CWL editor/conversion module. It gives hosts deterministic authoring, conversion, revision evidence, safe clipboard handling, SSR/form integration, local autosave coordination, and provider-neutral collaboration bindings without taking ownership of host transport, identity, tenancy, durable persistence, credentials, retention, deployment, or model-use policy. +Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. It gives hosts a TipTap/ProseMirror editor, safe rich clipboard handling, canonical document envelopes, revision-scoped evidence, SSR/native-form integration, bounded local autosave coordination, provider-neutral collaboration bindings, and deterministic Office conversion without taking ownership of host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, or model-use policy. + +The product promise is: **author, convert, collaborate, and prove document changes without hiding authority inside the editor.** ## Users and buyers -- Application developers embedding an editor into web and SSR applications. -- Enterprise platform teams requiring deterministic conversion, evidence, accessibility, security boundaries, and reproducible packages. -- CWL products such as naruon that compose Inkspan through stable package contracts. -- Operators and acquisition reviewers who need explicit ownership, release, security, and rollback evidence. +- Application developers embedding an editor into web, SSR, worker, or desktop-shell products. +- Enterprise platform teams requiring deterministic conversion, evidence, accessibility, security boundaries, reproducible packages, and explicit operational ownership. +- Authors and reviewers who need accessible Markdown/HTML editing, safe paste, import/export, and predictable recovery from save conflicts. +- CWL products such as naruon that compose Inkspan through `compose` / `ui.panel` while retaining host identity, persistence, collaboration-provider, and model policy. +- Acquisition, security, and operations reviewers who need a bounded source-of-truth graph for architecture, threats, tests, rollback, release evidence, and supported claims. + +## Jobs to be done + +1. Author and revise Markdown/HTML through one deterministic editor surface without losing canonical document identity. +2. Paste rich content while rejecting or sanitizing unsafe active, hidden, or resource-bearing input before it becomes editor state. +3. Import, export, and convert supported content deterministically, including independently reusable network-free Office DOCX/XLSX/PPTX rendering. +4. Detect exact content equality and stale review/selection state without copying complete document bodies into ordinary evidence metadata. +5. Save through a host-controlled durable boundary that prevents lost updates and makes conflict/ambiguous failure recoverable instead of silently successful. +6. Embed safely in SSR/native-form products while treating browser-submitted values as untrusted host input. +7. Add real-time collaboration without locking Inkspan to one provider or moving room authorization, awareness privacy, persistence, or tenant identity into the editor. +8. Compose Inkspan inside naruon or another CWL host without making those hosts required runtime dependencies for standalone adopters. +9. Offer model-assisted authoring only as host-approved untrusted proposals; deterministic editor/conversion validation remains authoritative. +10. Produce reviewable package, security, compatibility, accessibility, SBOM/provenance, and release evidence tied to one exact protected source head. ## Required outcomes -1. Author Markdown and HTML through a deterministic TipTap/ProseMirror surface. -2. Reject or sanitize unsafe rich clipboard input before it becomes editor state. -3. Produce versioned canonical document envelopes and SHA-256 revision evidence. -4. Bind selections and transitions to exact document revisions without copying document bodies into ordinary evidence metadata. -5. Support SSR-safe hydration and optional native form serialization while treating browser-submitted values as untrusted host input. -6. Coordinate bounded single-flight autosave with explicit conflict/failure recovery and server-selected strong validators. -7. Expose lifecycle observation only for externally visible state changes; construction and no-op operations must not manufacture lifecycle notifications. -8. Provide provider-neutral collaboration bindings while hosts retain collaboration transport, authorization, tenant isolation and durable audit ownership. -9. Preserve accessible keyboard, status and toolbar semantics. -10. Produce reproducible package and release evidence with fail-closed publication checks. +### Authoring and source fidelity + +- Markdown and HTML authoring use a deterministic TipTap/ProseMirror surface. +- Supported import/export behavior is explicitly versioned and testable; unsupported or lossy constructs are not silently advertised as lossless. +- Canonical document envelopes preserve exact schema/version identity and strict JSON/UTF-8 boundaries. +- Source and rendered/exported representations must have documented authority; generated output never silently becomes a new source of truth. + +### Clipboard and external content + +- Untrusted rich clipboard content is processed through the actual editor paste pipeline, not a disconnected helper. +- Active, hidden, executable, externally fetching, malformed, or over-limit input fails closed or is removed only under a documented semantic allowlist. +- Browser-parser differences that can change security semantics require real Chromium, Firefox, and WebKit differential acceptance before the relevant release line. + +### Evidence and concurrency + +- SHA-256 document revisions are equality evidence only, never authentication, tenant identity, authorization, signature, timestamp, or durable-write proof. +- Selection and transition evidence bind to one exact immutable editor state and omit document bodies from ordinary metadata. +- Autosave remains single-flight with bounded active/pending work and explicit conflict/failure recovery. +- Durable saves use a host/server-selected strong validator; conflict or ambiguous failure never silently advances it. +- Lifecycle observation emits only distinct externally visible document-free state transitions; construction and no-op operations do not manufacture notifications. + +### SSR and native forms + +- Server rendering never creates a browser editor view. +- Optional native-form serialization survives SSR/hydration and remains synchronized once the editor is authoritative. +- Hidden/native field values are client-controlled data and never replace host authentication, authorization, CSRF controls, request validation, tenant isolation, or durable concurrency. + +### Collaboration + +- Collaboration remains provider-neutral and compatible with host-supplied Yjs surfaces. +- Hosts own provider creation/destruction, room authorization, identities, awareness privacy, reconnect policy, update persistence, retention, encryption, and durable audit. +- Provider outage or degraded collaboration does not permit Inkspan to invent durable collaboration success or broader host authority. + +### Deterministic Office conversion + +- JSON→DOCX/XLSX/PPTX rendering is deterministic, network-free, macro-free, model-free, and Desktop-Office-free. +- Inputs are bounded and validated for XML 1.0, container/depth/cycle limits, worksheet/freeze-pane constraints, supported structures, and spreadsheet formula-injection boundaries. +- File publication is race-safe and explicit about overwrite behavior. +- Format-fidelity claims are limited to tested supported constructs; generated artifacts are verified through realistic package/document tests. + +### Modular composition and model assistance + +- Standalone Inkspan does not require naruon, contextual-orchestrator, a database, a provider SDK, or a model credential. +- A naruon host may compose Inkspan through a narrow client panel while host services retain authenticated transport, tenant persistence, collaboration provider, conflict UX, and model policy. +- Model output is untrusted proposed content. The host owns provider choice, credentials, redaction, external-data-use approval, logging, retention, and human approval; deterministic Inkspan validation remains the acceptance boundary. + +### Accessibility, print, and export + +- Native controls, focus behavior, keyboard parity, shortcut metadata, non-color status semantics, and host-facing lifecycle state support WCAG-oriented embedding. +- Application-visible saving/conflict/recovery messages must be derivable from programmatic state without Inkspan prescribing untranslated user-facing copy. +- Export/print surfaces must not rely on color alone or inaccessible interaction-only state where the corresponding product surface exists. ## Non-goals -Inkspan is not an identity provider, tenant database, durable document store, collaboration authorization server, deployment platform, model router, durable audit service, or merge/release authority for host applications. +Inkspan is not an identity provider, tenant database, durable document store, collaboration authorization server, deployment platform, credential manager, retention engine, model router, durable audit service, application migration owner, or merge/release authority for host products. + +Inkspan does not promise universal HTML/Office round-trip fidelity, arbitrary executable document content, implicit network fetching, model-generated content as trusted source, or silent migration of unknown document schemas. ## Security and privacy requirements -- Untrusted HTML, DOM capabilities, clipboard configuration, form values and host callbacks fail closed at documented boundaries. +- Untrusted HTML, DOM capabilities, clipboard configuration, form values, Office structures, host callbacks, collaboration updates, and model proposals fail closed at documented boundaries. - Active or hidden rich content must not bypass the supported semantic clipboard policy. -- Revision/entity tags are equality metadata, not credentials or authorization. -- Document bodies must not enter ordinary lifecycle, selection or transition evidence unless an explicit versioned contract requires them. -- Host applications remain responsible for authentication, authorization, CSRF, tenant isolation, persistence and retention. +- Spreadsheet formula-significant input must not silently become executable formulas unless a future explicit trusted formula contract says otherwise. +- Document bodies, revision/entity tags, provider metadata, tenant identifiers, prompts, and model outputs must not enter generic public metrics or unauthenticated logs. +- Host applications remain responsible for authentication, authorization, CSRF, tenant isolation, persistence, encryption, retention, audit storage, provider admission, and external-model policy. -## Reliability and concurrency requirements +## Reliability and operability requirements -- Autosave remains single-flight with bounded pending work. -- Conflict and ambiguous failure never silently advance durable validators. -- Observer failures cannot change save ordering or outcomes. -- No-op lifecycle operations must not emit a synthetic initial or duplicate snapshot. -- Async revision/selection capture must bind to one immutable editor state. +- Autosave is bounded, single-flight, idempotency-aware at its local contract, and explicit about blocked/conflict/failure state. +- Observer failures cannot change save ordering, result classification, or durable-validator handoff. +- Async revision/selection capture binds to one immutable editor state. +- Conversion/publication never reports a partial artifact as successful output. +- Package/release operations fail closed on stale source, ambiguous artifact inventory, digest mismatch, missing required evidence, or stale review/check state. +- Boundary-specific rollback must preserve canonical document readability and host-owned durable state. -## Accessibility requirements +## Packaging and acquisition acceptance -Native controls, focus behavior, shortcut metadata and host-facing lifecycle state must support WCAG-oriented embedding. Machine state is not user-facing wording; localization and application-level live-region policy remain host responsibilities. +A release is acceptable only from an exact integrated protected head with applicable CI/security checks, exact owned production statement/branch/function/line coverage, complete public docstrings where required, package-consumer compatibility, real browser/document-fidelity evidence, accessibility evidence, SBOM/provenance/reproducibility, zero valid unresolved findings, required independent non-author review, rollback guidance, and verified published artifacts. -## Packaging and release acceptance +Shareable acquisition evidence excludes production tenant content and credentials. Protected `main`, exact-head machine evidence, formal reviews, and canonical product documentation outrank historical PR bodies, comments, local-only results, or predecessor-head status. -A release is acceptable only from an exact integrated protected head with required CI/security checks, exact owned production coverage, package-consumer compatibility, reproducibility/provenance evidence, zero valid unresolved findings, required independent review, rollback guidance and verified release artifacts. +## Current, proposed, and planned scope -## Current and planned scope +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. -Protected main is the authority for implemented behavior. Open PRs may describe Proposed/Active work but are not shipped contracts until protected integration. Provider-neutral collaboration, autosave, review evidence and release hardening evolve through versioned public contracts rather than hidden host coupling. +Current open development lines include richer browser-verified clipboard assurance, lifecycle observation, document-transition/revision evidence, SSR/native-form integration, accessibility metadata, release hardening, and security disclosure documentation. Their detail is useful design evidence but remains Proposed until merged. A future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. From 9692105fc038ea2c349c4882bc4abc92aed04711 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:16:03 +0900 Subject: [PATCH 025/101] docs(tech): complete canonical Inkspan technical requirements --- docs/TRD.md | 101 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/docs/TRD.md b/docs/TRD.md index 9a28342a..01059420 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -2,52 +2,107 @@ Status: Proposed canonical baseline -## Runtime boundary +## Authority and runtime boundary -Inkspan owns deterministic editor, conversion and local coordination code. Hosts own network transport, authentication/authorization, tenant isolation, durable persistence, credentials, migrations, retention, durable audit storage, deployment and model-use policy. +Inkspan owns deterministic editor, conversion, document-envelope, local evidence, local autosave ordering, accessibility metadata, package, and provider-neutral adapter behavior. Hosts own network transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, durable audit storage, deployment, collaboration-provider lifecycle, and model-use policy. -## Document identity +Protected `main` is the implementation authority. Open PRs may provide Proposed contracts or evidence but do not become shipped behavior until protected integration. -A versioned document envelope is validated before canonicalization or hashing. SHA-256 revision evidence identifies exact canonical content. Local content digests do not replace server-selected RFC 9110 strong validators for durable compare-and-swap. +## Package and module boundaries -## Clipboard boundary +The root product may compose TipTap/ProseMirror, React-facing integration, deterministic conversion, revision evidence, autosave, collaboration adapters, email/base64 utilities, and Office rendering. Framework-independent subpaths must not accidentally require React, DOM globals, TipTap UI, ProseMirror view, Yjs, network, credentials, database clients, or model SDKs when their public contract excludes those dependencies. -Rich clipboard HTML is untrusted. Sanitization must be installed in the actual TipTap v2/ProseMirror paste pipeline, use bounded fail-closed validation, avoid external fetch or active execution, and preserve only supported semantic content. Pure sanitizer APIs and editor integration must remain behaviorally consistent. +Standalone use must not require naruon or contextual-orchestrator. A CWL host can compose Inkspan additively through stable interfaces. + +## Document identity and schema boundary + +A versioned `document_envelope` is validated before canonicalization or hashing. Strict JSON text/byte handling rejects malformed input, duplicate object names, malformed UTF-8, unsupported schemas, hostile JavaScript object descriptors, and resource-limit violations according to the active contract. + +SHA-256 revision evidence identifies exact canonical content. Local content digests are equality evidence only and never replace server-selected RFC 9110 strong validators for durable compare-and-swap. Unknown schema migration remains host-owned; a future identity-inspection helper may expose routing metadata without becoming a permissive current-schema parser or migration executor. + +## Markdown/HTML editor boundary + +TipTap/ProseMirror is the deterministic editing authority for supported Markdown/HTML behavior. Import/export adapters must state supported and lossy constructs explicitly. Generated or rendered output does not silently replace canonical source state. Editor integrations validate extension/plugin configuration and public callback boundaries fail closed without executing accessors merely to inspect untrusted configuration. + +## Rich clipboard boundary + +Rich clipboard HTML is untrusted. Sanitization must be installed in the actual TipTap/ProseMirror paste pipeline, use bounded fail-closed validation, perform no external fetch or active execution, and preserve only supported semantic content. Pure sanitizer APIs and editor integration must remain behaviorally consistent. + +Where browser fragment parsing or serialization can change security semantics, a release must run the same adversarial corpus through dependency-locked Playwright Chromium, Firefox, and WebKit projects. Differences require an explicit standards/threat rationale rather than an unconditional parity normalization. ## SSR and native forms -Server rendering must not instantiate an editor view. When a native field is explicitly enabled, SSR/hydration serializes the selected controlled value as escaped input data. The value is client-controlled submission data, never authorization, CSRF protection, signature or durable-write evidence. +Server rendering must not instantiate an editor view. When a native field is explicitly enabled, SSR/hydration serializes the selected controlled Markdown/HTML value as escaped client-controlled input. Once the editor is authoritative, document transactions synchronously mirror the configured serialization into the form field. + +The hidden/native field is never authentication, authorization, CSRF protection, tenant identity, signature, integrity proof, or durable-write evidence. Hosts independently validate and authorize submissions. ## Revision-scoped evidence -Selection evidence captures selection coordinates and revision from the same immutable editor state before asynchronous hashing. Transition evidence validates previous and resulting envelopes before sequential revision derivation and contains revision metadata rather than document bodies. +Selection evidence captures structural coordinates and canonical document state from the same immutable editor snapshot before asynchronous hashing. Transition evidence validates previous and resulting envelopes before sequential revision derivation. Ordinary evidence contains revision/coordinate/change metadata rather than document bodies and does not synthesize actor, tenant, time, model identity, signature, authorization, transport result, or durable-persistence claims. + +## Autosave state machine and durable concurrency + +States are `idle`, `saving`, `blocked`, `closing`, and `closed`, with explicit blocked reasons. The local queue remains single-flight and retains bounded active/pending work and bounded flush waiters. Evidence supplied to a callback is immutable and validated before scheduling. + +Durable sessions carry a host/server-selected strong HTTP entity tag. Successful host callbacks may advance the durable validator only from a validated replacement strong tag. Conflict, malformed result, callback failure, hostile reflection, promise-assimilation failure, timeout/network ambiguity, or explicit host failure never silently advances it. + +Lifecycle observation is optional and bounded to one construction-time callback. Construction emits nothing. Only distinct externally visible document-free snapshots are emitted. A method call producing no visible lifecycle transition, including a no-op `resume()`, emits nothing. Observer exceptions are isolated from queue ordering, save outcomes, recovery, and durable-validator handoff. + +## Provider-neutral collaboration + +Inkspan may bind to host-supplied Yjs-compatible document/awareness surfaces. Inkspan does not create/destroy production network providers and does not own room identity, tenant admission, user identity, authorization, provider credentials, reconnect policy, awareness privacy, update persistence, retention, encryption, or durable audit. + +Provider updates and awareness state are untrusted tenant data, not authorization evidence. Provider outage/degraded mode is resolved by host policy; Inkspan must not invent durable collaboration success. + +## Deterministic conversion and Office renderer + +Deterministic conversion is an authority boundary separate from model-assisted authoring. Model output may become a proposed document change, but deterministic editor/conversion validation decides whether the resulting content is structurally acceptable. + +The Office JSON→DOCX/XLSX/PPTX renderer is **network-free**, **macro-free**, model-free, and Desktop-Office-free. It must: + +- validate the versioned input contract before publication; +- reject invalid XML 1.0 content and unsupported/non-JSON structures; +- bound bytes, strings, values, nesting, containers, and cyclic/aliased input according to the active renderer contract; +- enforce Excel worksheet-name, workbook, row/column, freeze-pane, and supported-cell limits; +- neutralize untrusted spreadsheet **formula**-significant strings under the supported value contract rather than silently creating formulas; +- preserve deterministic package metadata and supported document structure; +- publish through race-safe file operations with explicit overwrite semantics; and +- fail closed without reusing partial artifacts after validation or write failure. + +Format-fidelity claims are limited to tested supported constructs. The renderer does not execute macros, scripts, formula calculation, embedded external resources, or Desktop Office automation. + +## Model-assisted authoring + +Inkspan does not own model credentials, provider routing, prompt retention, external-data-use approval, tenant disclosure policy, or model audit. A host may route assistance through contextual-orchestrator or another approved provider. Model output is untrusted proposed content and cannot bypass deterministic clipboard/document/conversion validation, user/host approval, or durable save authorization. + +## Naruon and CWL composition -## Autosave state machine +A naruon host may mount Inkspan through `compose` / `ui.panel` using a narrow client boundary. The host supplies serializable non-secret configuration, authenticated API calls, server-selected strong validators, accessible conflict/recovery UX, provider lifecycle, and optional model routing. Cross-document mounts use explicit host state/identity so editor/autosave state cannot bleed across documents. -States are `idle`, `saving`, `blocked`, `closing`, and `closed`, with explicit blocked reasons. The queue retains bounded active/pending work and exposes immutable document-free snapshots. Durable sessions carry a host-owned strong validator that advances only after a validated saved result. +Central `.github` automation, contextual-orchestrator, and other CWL repositories are external bounded contexts. Inkspan does not copy a central defect locally merely to make a leaf gate green. -Lifecycle observers are optional and bounded to one construction-time callback. They receive only distinct externally visible state snapshots. Construction emits nothing. A method call that produces no externally visible state transition, including `resume()` returning false, emits nothing. Observer exceptions are isolated from persistence behavior. +## Failure and diagnostic semantics -## Collaboration +Public failures are bounded, deterministic where practical, and redacted. Document bodies, credentials, tenant identifiers, complete provider metadata, callback values, private exception causes, prompts/model output, and durable validators are not reflected into generic public diagnostics unless a versioned authorized contract explicitly requires them. -Collaboration bindings are provider-neutral. Inkspan may adapt editor state to Yjs-compatible surfaces, but provider lifecycle, identity, awareness privacy, tenant authorization, persistence and durable audit remain host responsibilities. +Cancellation, retry/offline policy, network timeout budgets, durable reconciliation, and user-facing localized recovery remain host responsibilities when they involve host transport or persistence. -## Failure semantics +## Accessibility and interaction semantics -Public failures are bounded and redacted. Host callback exceptions, malformed callback results, hostile reflection/accessors, invalid envelopes, invalid UTF-8 and unsafe clipboard input must not leak private values or silently succeed. Cancellation and host-owned transport policy remain explicit. +Shipped keyboard behavior, focus behavior, native controls, `aria-pressed`, `aria-keyshortcuts`, programmatic save/conflict state, and visible shortcut documentation must agree. Status must not depend on color alone. Inkspan exposes machine state sufficient for host WCAG-oriented messaging while leaving localization and application-specific live-region policy to the host. -## Accessibility +## Packaging, compatibility, and release evidence -Shipped keyboard behavior and programmatic shortcut metadata must agree. Host-visible save/conflict state must be sufficient for accessible application messaging without prescribing localized wording. +The root package and framework-independent subpaths are verified from packed artifacts under ESM, CommonJS, and strict TypeScript consumers. Office Python surfaces are verified under the documented supported Python matrix, exact production statement/branch coverage, complete public docstrings, built wheel/package inspection, and license/dependency consistency. -## Packaging and compatibility +Release publication verifies one exact integrated protected source head, expected artifact inventory and digests, package/runtime compatibility, security/coverage/accessibility/document-fidelity gates, SBOM/provenance/reproducibility where configured, zero valid unresolved findings, formal review/branch-protection requirements, and post-publication artifact smoke evidence. -The root package and framework-independent subpaths must remain consumable from packed ESM/CommonJS and strict TypeScript environments without accidental React/DOM/framework dependencies where the subpath contract excludes them. Office artifacts follow their separately versioned package contract. +Queued, cancelled, skipped-required, absent, stale-head, predecessor-head, status-only, author-only, or synthetic-merge evidence is not success. A commit status, automated model verdict, comment, formal review, and merge authority are distinct evidence classes. -## Evidence and governance +## Security, privacy, and operability dependencies -Check runs, commit statuses, automated model verdicts, formal reviews and merge authority are distinct evidence classes. Exact-head evidence does not transfer after source movement. Comments or textual approvals are not formal approval. Release publication must fail closed on ambiguous/stale artifact inventory or digest mismatch. +`docs/THREAT_MODEL.md`, `docs/TEST_STRATEGY.md`, `docs/OPERABILITY.md`, `docs/TRACEABILITY.md`, and the detailed ADR corpus are part of this technical contract. `SECURITY.md` is separately owned by the open security-disclosure PR until that bounded line reaches protected `main`; this branch must not duplicate/race it. -## Implemented versus planned +## Implemented versus proposed -Protected `main` is the sole implemented baseline. Open PRs are Active/Proposed evidence only until protected merge. Documentation must not convert an unmerged feature into an Accepted shipped claim. +Protected `main` is the sole implemented baseline. Requirements describing open clipboard, autosave observation, transition/selection evidence, SSR/native-form, accessibility, release-hardening, or security-disclosure PRs are Proposed until merged. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. From 60802e56236ac3f520e42d6f6651bb2761bcd161 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:18:21 +0900 Subject: [PATCH 026/101] docs(uml): complete Inkspan runtime and deployment diagrams --- docs/UML.md | 255 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 228 insertions(+), 27 deletions(-) diff --git a/docs/UML.md b/docs/UML.md index f9fd0ed6..9b7ece0e 100644 --- a/docs/UML.md +++ b/docs/UML.md @@ -2,22 +2,43 @@ Status: Proposed canonical baseline -## Component topology +These diagrams describe the accepted product boundary. Protected `main` remains implementation authority; elements owned by open PRs are Proposed until integrated. + +## Bounded-context and component topology ```mermaid flowchart LR - HostApp[Host application] --> EditorCore[Inkspan editor] - EditorCore --> ConversionCore[Deterministic conversion] - EditorCore --> ClipboardBoundary[Safe clipboard] - EditorCore --> EvidenceCore[Revision and selection evidence] - EditorCore --> AutosaveCore[Local autosave coordinator] - EditorCore --> CollaborationAdapter[Provider-neutral collaboration adapter] - AutosaveCore --> HostSave[Host durable save callback] - CollaborationAdapter --> HostProvider[Host collaboration provider] - HostApp --> HostAuthority[Host auth tenancy persistence audit] + User[Author or reviewer] + HostApp[Standalone host or naruon compose / ui.panel] + EditorCore[Inkspan TipTap / ProseMirror editor] + ClipboardBoundary[Safe rich clipboard] + EvidenceCore[Envelope revision selection transition evidence] + AutosaveCore[Bounded local autosave] + ConversionCore[Deterministic Markdown / HTML conversion] + OfficeRenderer[Deterministic Office renderer] + CollaborationAdapter[Provider-neutral Yjs adapter] + HostProvider[Host-owned Yjs provider] + HostStore[Host persistence / audit] + ModelGateway[Host-approved contextual-orchestrator or model gateway] + ControlPlane[ContextualWisdomLab/.github control plane] + + User --> HostApp + HostApp --> EditorCore + EditorCore --> ClipboardBoundary + EditorCore --> EvidenceCore + EditorCore --> AutosaveCore + EditorCore --> ConversionCore + ConversionCore --> OfficeRenderer + EditorCore <--> CollaborationAdapter + CollaborationAdapter <--> HostProvider + AutosaveCore --> HostStore + HostApp --> ModelGateway + ControlPlane -. CI security review provenance release policy .-> EditorCore ``` -## Paste sequence +The host owns transport, authentication, authorization, tenant isolation, persistence, credentials, provider lifecycle, retention, deployment, durable audit, and model-use policy. Inkspan owns deterministic local editor/conversion/evidence behavior only. + +## Rich paste sequence ```mermaid sequenceDiagram @@ -27,30 +48,132 @@ sequenceDiagram participant EditorState UserClipboard->>PastePipeline: rich HTML PastePipeline->>SafeClipboard: transform pasted HTML - SafeClipboard->>SafeClipboard: bounded inert parse and allowlist - SafeClipboard-->>PastePipeline: sanitized content or bounded failure - PastePipeline->>EditorState: parse and transact only accepted content + SafeClipboard->>SafeClipboard: bounded inert parse and semantic allowlist + alt accepted + SafeClipboard-->>PastePipeline: sanitized supported content + PastePipeline->>EditorState: parse and transact accepted content + else malformed, active, hidden, resource-bearing, or over limit + SafeClipboard-->>PastePipeline: bounded failure / safe omission + end ``` -## Autosave sequence and no-op rule +Security-relevant browser fragment semantics require the same hostile corpus under Chromium, Firefox, and WebKit before the relevant release line. + +## Author-to-model proposal sequence + +```mermaid +sequenceDiagram + participant Author + participant Host as Host / naruon + participant Gateway as Host-approved model gateway + participant Editor as Inkspan editor + participant Validator as Deterministic Inkspan validation + + Author->>Host: request assistance for explicit document scope + Host->>Host: authorize tenant and external model use + Host->>Gateway: send host-approved bounded context + Gateway-->>Host: untrusted proposed content + Host->>Editor: present proposal without durable apply + Editor->>Validator: parse / sanitize / convert / validate proposal + Validator-->>Author: diff and validation result + alt author / host approves + Author->>Editor: apply proposal to local document state + else rejected or invalid + Author-->>Editor: keep current document + end +``` + +Model output never bypasses deterministic validation, host authorization, user review, or durable save concurrency. + +## Import and export flow + +```mermaid +flowchart LR + Source[Supported Markdown / HTML or versioned envelope] + Validate[Strict bounded validation] + Editor[Inkspan editor state] + ExportChoice{Requested deterministic output} + Markdown[Markdown] + Html[HTML] + OfficeRequest[Versioned Office render request] + Office[DOCX / XLSX / PPTX artifact] + + Source --> Validate --> Editor --> ExportChoice + ExportChoice --> Markdown + ExportChoice --> Html + ExportChoice --> OfficeRequest --> Office +``` + +Unsupported or lossy constructs are surfaced by the relevant contract instead of being advertised as lossless round-trip fidelity. + +## Office render and file publication sequence + +```mermaid +sequenceDiagram + participant Caller + participant Renderer as Deterministic Office renderer + participant Validator + participant Builder + participant Publisher as Race-safe file publication + participant Artifact + + Caller->>Renderer: versioned JSON render request + Renderer->>Validator: validate schema, XML, limits, names, freeze panes, values + Validator->>Validator: neutralize supported untrusted formula-significant strings + alt invalid or unsupported + Validator-->>Caller: bounded failure, no successful artifact + else valid + Validator->>Builder: validated inert model + Builder->>Builder: build network-free macro-free Office package + Builder->>Publisher: complete candidate artifact + alt publication succeeds under explicit overwrite policy + Publisher-->>Artifact: committed DOCX / XLSX / PPTX + Artifact-->>Caller: deterministic artifact result + else publication fails or conflicts + Publisher-->>Caller: bounded failure, partial output is not success + end + end +``` + +## File publication state machine + +```mermaid +stateDiagram-v2 + [*] --> validating + validating --> rejected: invalid / unsupported / over limit + validating --> building: validated request + building --> failed: build failure + building --> publishing: complete candidate package + publishing --> committed: publication succeeds + publishing --> conflicted: existing target without approved overwrite + publishing --> failed: write / race / validation failure + committed --> [*] + rejected --> [*] + conflicted --> [*] + failed --> [*] +``` + +No failed or partial file publication becomes a successful conversion artifact. + +## Autosave sequence and no-op observer rule ```mermaid sequenceDiagram participant Host participant Queue participant DurableSave - Host->>Queue: enqueue revision evidence + Host->>Queue: enqueue immutable revision evidence Queue-->>Host: saving snapshot when observer exists - Queue->>DurableSave: one active save - DurableSave-->>Queue: saved or conflict/failure + Queue->>DurableSave: one active save with host strong validator + DurableSave-->>Queue: saved or conflict / ambiguous failure alt saved - Queue-->>Host: next distinct lifecycle snapshot + Queue-->>Host: next distinct lifecycle snapshot and coherent replacement validator else blocked Queue-->>Host: blocked snapshot - Host->>Queue: resume + Host->>Queue: authenticated recovery / resume alt resume changes state Queue-->>Host: next distinct lifecycle snapshot - else resume is false/no-op + else resume is false / no-op Queue-->>Host: no observer notification end end @@ -81,10 +204,12 @@ sequenceDiagram participant Browser participant Editor participant NativeForm + participant Host Server-->>Browser: escaped controlled native field value Browser->>Editor: client hydration and editor creation Editor->>NativeForm: mirror serialization on document transaction NativeForm-->>Host: untrusted submitted value + Host->>Host: authenticate, authorize, validate, enforce tenant and concurrency policy ``` ## Selection and revision capture @@ -95,18 +220,94 @@ sequenceDiagram participant EditorState participant RevisionDerivation Caller->>EditorState: request selection revision evidence - EditorState->>EditorState: capture one immutable state and selection + EditorState->>EditorState: capture one immutable state and structural selection EditorState->>RevisionDerivation: canonical envelope from same state RevisionDerivation-->>Caller: frozen revision and structural coordinates ``` -## Authority boundaries +## Provider-neutral Yjs collaboration sequence + +```mermaid +sequenceDiagram + participant Host + participant Provider as Host-owned Yjs provider + participant YDoc as Host-supplied Yjs document + participant Inkspan + participant Awareness as Host-governed awareness + + Host->>Provider: authenticate / authorize room and create lifecycle + Provider<->>YDoc: synchronize host-owned updates + Host->>Inkspan: mount with supplied YDoc / awareness binding + Inkspan<->>YDoc: deterministic editor binding + Inkspan<->>Awareness: bounded awareness presentation + Note over Inkspan,Provider: Inkspan does not own credentials, room authorization, persistence, retention, or provider destruction + Host->>Inkspan: unmount panel / editor + Host->>Provider: retain or destroy provider according to host lifecycle +``` + +## naruon modular composition + +```mermaid +flowchart TB + Route[naruon route / product shell] + Panel[naruon compose / ui.panel client boundary] + Inkspan[Inkspan editor module] + HostApi[Authenticated host API] + Persistence[Host persistence and audit] + Yjs[Host-owned Yjs provider] + Orchestrator[Optional contextual-orchestrator] + + Route --> Panel --> Inkspan + Panel --> HostApi --> Persistence + Inkspan <--> Yjs + Panel --> Orchestrator + Orchestrator -. untrusted proposal .-> Panel +``` + +Inkspan remains importable without naruon or contextual-orchestrator. + +## Deployment topology + +```mermaid +flowchart LR + Browser[Browser / desktop webview] + InkspanJs[Inkspan JS/TS package] + OfficeProcess[Optional deterministic Office renderer process/library] + HostBackend[Host backend] + HostDb[Host durable store] + HostYjs[Host collaboration provider] + HostModel[Host model gateway] + + Browser --> InkspanJs + InkspanJs -->|host callback / application API| HostBackend + HostBackend --> HostDb + Browser <--> HostYjs + HostBackend --> HostModel + InkspanJs -->|explicit conversion request in supported deployment| OfficeProcess +``` + +The diagram does not imply a required network service owned by Inkspan. The Office renderer may be used as an independent library/tool under its package contract. + +## Failure and degraded modes + +```mermaid +flowchart TD + Event{Failure boundary} + Event -->|clipboard / import invalid| LocalReject[Reject safely; editor remains usable] + Event -->|durable save conflict / ambiguity| SaveBlocked[Blocked until explicit host recovery] + Event -->|Yjs provider unavailable| CollabDegraded[Host chooses local edit / read-only / reconnect / block] + Event -->|model gateway unavailable| ManualMode[Deterministic manual editing continues] + Event -->|Office render invalid / publication fails| RenderFailed[No successful artifact; source document preserved] + Event -->|release evidence stale / incomplete| ReleaseBlocked[No publication] +``` + +## Authority and release evidence flow ```mermaid flowchart TB - InkspanAuthority[Inkspan deterministic authority] --> EditorSemantics[Editor conversion revision semantics] - HostAuthority[Host authority] --> HostServices[Transport identity tenancy persistence audit] - MachineEvidence[CI security package provenance] --> ProtectedMerge[Protected merge] + InkspanAuthority[Inkspan deterministic authority] --> EditorSemantics[Editor / conversion / revision semantics] + HostAuthority[Host authority] --> HostServices[Transport / identity / tenancy / persistence / audit / model policy] + MachineEvidence[Exact-head CI / security / package / browser / Office / provenance] --> ProtectedMerge[Protected merge] IndependentReview[Independent formal review where required] --> ProtectedMerge - ProtectedMerge --> ReleaseAuthority[Release authority] + ProtectedMerge --> ReleaseAuthority[Exact protected release authority] ``` From 1701d8c69ce1a828348bf899bd4d122178563c56 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:19:05 +0900 Subject: [PATCH 027/101] docs(model): complete conceptual Inkspan evidence model --- docs/DATA_MODEL.md | 101 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/docs/DATA_MODEL.md b/docs/DATA_MODEL.md index 0744ef06..178c3d0d 100644 --- a/docs/DATA_MODEL.md +++ b/docs/DATA_MODEL.md @@ -2,39 +2,104 @@ Status: Proposed canonical baseline -Inkspan does not own an application database. This document is a conceptual/logical model of value objects and host boundaries; it must not be read as physical DDL. +Inkspan does **not** own an application database in the current architecture. This document is a conceptual/logical model of runtime value objects, conversion/release evidence, and host-owned boundaries. It must not be read as physical DDL. Entities marked host-owned may be persisted by an embedding product, but their physical schema is outside Inkspan authority. + +## Logical ERD ```mermaid erDiagram document_envelope ||--|| document_revision : derives + editor_session ||--o{ document_revision : observes document_revision ||--o{ document_transition : previous_or_resulting document_revision ||--o{ selection_evidence : binds document_revision ||--o{ autosave_revision : queues autosave_revision }o--|| autosave_snapshot : appears_in durable_validator ||--o{ autosave_snapshot : accompanies - collaboration_session }o--o{ document_revision : coordinates + + collaboration_document ||--o{ provider_binding : supplied_through + collaboration_document ||--o{ awareness_state : exposes + provider_binding }o--|| host_capability : requires + collaboration_document }o--o{ editor_session : coordinates + clipboard_policy ||--o{ document_envelope : constrains_input + + document_envelope ||--o{ conversion_request : source_for + conversion_request ||--o| conversion_artifact : produces + conversion_request ||--o{ render_warning : records + conversion_artifact ||--o{ audit_event : host_may_record + release_artifact }o--|| release_evidence : verified_by + release_evidence ||--o{ audit_event : host_or_release_system_records ``` -## Entities +## Inkspan-owned in-memory or package value objects + +- `document_envelope`: versioned, strictly validated, canonicalizable complete document value. It can contain the complete document body. Inkspan constructs/validates it; a host may persist it under its own policy. +- `document_revision`: SHA-256 equality evidence derived from one exact canonical envelope. It is not authorization, tenant identity, actor identity, timestamp, signature, or proof of a durable write. +- `editor_session`: conceptual local editor/runtime lifetime. It binds one mounted editor state to local evidence and host callbacks. It is not a durable account/session record and has no authentication authority. +- `document_transition`: previous/resulting revision pair plus changed classification. It deliberately omits the document body from ordinary evidence. +- `selection_evidence`: ProseMirror structural coordinates bound to one exact revision. It is a local evidence value, not a durable cross-revision anchor. +- `autosave_revision`: detached immutable revision evidence accepted by the local single-flight autosave coordinator. +- `autosave_snapshot`: frozen document-free queue/session lifecycle metadata such as idle/saving/blocked/closing/closed and bounded pending state. +- `clipboard_policy`: bounded local policy describing the supported semantic rich-paste boundary. It grants no host network or tenant authority. +- `conversion_request`: versioned deterministic conversion intent. It identifies the supported source representation, requested target such as Markdown/HTML/DOCX/XLSX/PPTX, explicit output/publication options, and validated render configuration. It is a runtime value, not a durable job record. +- `conversion_artifact`: completed deterministic conversion result or artifact identity produced only after validation/build/publication succeeds. A partial/failed output is not a `conversion_artifact` success. +- `render_warning`: bounded structured warning or limitation attached to a supported conversion request/result when the contract permits warning-level evidence. It must not contain secrets or uncontrolled complete document bodies in generic telemetry. +- `release_artifact`: package/wheel/checksum or other expected artifact considered for release. +- `release_evidence`: exact-source artifact inventory/digest/provenance/verification evidence used before publication. + +## Host-owned conceptual entities and boundaries + +- `durable_validator`: host/server-selected strong HTTP entity tag used for durable compare-and-swap. Inkspan validates/coordinates the value but does not select durable server state. +- `collaboration_document`: host-owned Yjs-compatible collaborative document state supplied to Inkspan. Room identity, tenant membership, persistence and retention remain host responsibilities. +- `awareness_state`: host/provider-governed ephemeral collaboration presence metadata. It can contain sensitive tenant information and is not authorization evidence. +- `provider_binding`: host-created connection/binding between an Inkspan collaboration adapter and a collaboration provider/document. Inkspan does not own credentials, reconnect policy, provider creation/destruction, or durable update storage. +- `host_capability`: conceptual set of explicitly supplied host capabilities such as durable save callback, authenticated API, collaboration provider, external model proposal surface, file-output authority, or naruon panel composition. Absence of a capability means Inkspan must not invent it. +- `audit_event`: host/release-system owned durable event for actor, authorization, durable save, migration, provider, security, or release activity. Inkspan local revisions/transitions/snapshots do not substitute for authenticated durable audit records. + +## Ownership and lifecycle matrix + +| Entity | Current physical persistence owner | Typical lifecycle | Contains complete document body? | Authority claim | +|---|---|---|---|---| +| `document_envelope` | host if persisted | document revision | yes | deterministic document value only | +| `document_revision` | local or host metadata by policy | derived per exact content | no | equality only | +| `editor_session` | none required | mounted editor runtime | may reference local state | no auth/session authority | +| `document_transition` | none required; host may store | change evidence | no | content-lineage evidence only | +| `selection_evidence` | none required | review/selection capture | no | exact-revision coordinates only | +| `autosave_revision` | none required | queued local save evidence | envelope-bearing evidence may be retained boundedly by queue | local save ordering only | +| `autosave_snapshot` | none required | lifecycle observation | no | local machine state only | +| `durable_validator` | host | durable version | no | host concurrency evidence, not authorization | +| `collaboration_document` | host/provider | collaborative room/document | yes, as Yjs state | host/provider authority | +| `awareness_state` | host/provider | ephemeral presence | not normally document body | no authorization | +| `provider_binding` | host | mount/connection lifecycle | no | host connection capability | +| `host_capability` | host/runtime configuration | component mount | no | explicit capability only | +| `conversion_request` | none required | one deterministic conversion | may reference/contain requested source content | conversion intent only | +| `conversion_artifact` | caller/host filesystem or artifact store | successful render/export | yes, rendered form | successful deterministic output only | +| `render_warning` | none required; host may log under policy | conversion result | no by default | warning/limitation only | +| `audit_event` | host/release system | durable operational history | should avoid complete body unless policy requires | authenticated host/release evidence | +| `release_artifact` | release system | build/release | package content | candidate artifact only | +| `release_evidence` | release system | exact-head publication | no tenant document content | artifact/source verification only | + +## Temporal, tenant, provenance, and version dimensions + +The current Inkspan runtime does not create a tenant database, but products embedding it depend on temporal/version provenance boundaries: + +- `document_envelope` carries an explicit schema/version contract; unknown versions require host-owned migration routing rather than permissive parsing. +- `document_revision`, selection, transition, and autosave evidence bind to one exact content state; they do not add actor/time/tenant claims not present in the source contract. +- `durable_validator` is temporally ordered by the host's atomic persistence service and must advance only after validated durable success. +- `collaboration_document`, `provider_binding`, `awareness_state`, `host_capability`, and `audit_event` can be tenant-scoped in a host, but Inkspan does not define or infer that tenant key. +- `release_evidence` binds package artifacts to one exact protected source generation; predecessor evidence does not transfer after source movement. -- `document_envelope`: versioned validated canonicalizable document value. In-memory/package value; host may persist it. -- `document_revision`: SHA-256 equality evidence derived from one validated canonical envelope. Value object, not authorization. -- `document_transition`: previous/resulting revision pair plus changed classification. Value object without document body. -- `selection_evidence`: ProseMirror structural coordinates bound to one exact revision. Value object, not a durable cross-revision anchor. -- `autosave_revision`: detached immutable revision evidence accepted by local autosave coordination. -- `autosave_snapshot`: frozen document-free queue/session lifecycle metadata. -- `durable_validator`: host/server-selected strong HTTP entity tag used for durable compare-and-swap. Host-owned concurrency evidence. -- `collaboration_session`: conceptual host/provider lifecycle around collaborative editor state. Provider/authorization/persistence are host-owned. -- `clipboard_policy`: bounded local policy controlling accepted rich clipboard semantics. -- `release_artifact`: package/wheel/checksum artifact considered for release. -- `release_evidence`: digest/inventory/provenance evidence used before publication. +## Privacy and minimum-disclosure rules -## Ownership +Ordinary lifecycle/selection/transition evidence should remain document-free. Revision/entity tags, provider metadata, awareness state, and host identifiers can still be tenant-confidential metadata and must not become public high-cardinality metric labels or unauthenticated logs. Complete document envelopes, Yjs state, conversion inputs/artifacts, prompts/model outputs, credentials, and host authorization claims follow the host's purpose, encryption, retention, and access policy. -Inkspan owns deterministic construction and validation of its value objects. Hosts own durable identifiers, actors, tenants, timestamps, storage records, credentials, audit events, authorization decisions, retention and migrations unless a future explicit versioned contract states otherwise. +## Persistence non-applicability and future change -## Persistence non-applicability +No Inkspan-owned relational schema is required by the current architecture, so no physical database ERD or migration set is invented here merely to satisfy documentation completeness. If Inkspan later introduces durable persistence, that is a material architecture change requiring: -No Inkspan-owned relational schema is required by the current architecture. If Inkspan later introduces durable persistence, that is a material architecture change requiring an ADR, migration/rollback design, security review and a physical ERD distinct from this conceptual model. +1. an Accepted ADR defining why persistence moved into Inkspan; +2. a physical ERD with descriptive multiword `snake_case` object names; +3. tenant, temporal, provenance, retention, encryption, authorization, and audit semantics; +4. migrations, backup/restore and rollback/recovery design; and +5. a revised threat model, test strategy, operability runbook, and acquisition evidence package. From 6e3e172c0ce4d88ba2e414591702a47faf66d96b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:29:53 +0900 Subject: [PATCH 028/101] test(docs): require canonical interface contracts --- src/canonicalProductDocumentation.test.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index 8fe9e181..d8709b53 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -9,6 +9,7 @@ const repositoryFile = (path: string): string => const requiredFiles = [ 'docs/PRD.md', 'docs/TRD.md', + 'docs/CONTRACTS.md', 'docs/UML.md', 'docs/DATA_MODEL.md', 'docs/THREAT_MODEL.md', @@ -38,10 +39,11 @@ describe('canonical product documentation graph', () => { it('records host ownership and deterministic Inkspan authority consistently', () => { const prd = repositoryFile('docs/PRD.md'); const trd = repositoryFile('docs/TRD.md'); + const contracts = repositoryFile('docs/CONTRACTS.md'); const threatModel = repositoryFile('docs/THREAT_MODEL.md'); const operability = repositoryFile('docs/OPERABILITY.md'); - for (const document of [prd, trd, threatModel, operability]) { + for (const document of [prd, trd, contracts, threatModel, operability]) { expect(document).toContain('host'); expect(document).toMatch(/transport|authorization|tenant|persistence/i); } @@ -54,6 +56,7 @@ describe('canonical product documentation graph', () => { it('preserves the durable product decisions from the canonical conversation', () => { const prd = repositoryFile('docs/PRD.md'); const trd = repositoryFile('docs/TRD.md'); + const contracts = repositoryFile('docs/CONTRACTS.md'); const uml = repositoryFile('docs/UML.md'); const dataModel = repositoryFile('docs/DATA_MODEL.md'); @@ -63,6 +66,16 @@ describe('canonical product documentation graph', () => { for (const marker of ['network-free', 'macro-free', 'formula', 'Office']) { expect(trd).toContain(marker); } + for (const marker of [ + 'document envelope', + 'autosave', + 'collaboration', + 'naruon', + 'host-owned', + 'versioned', + ]) { + expect(contracts).toContain(marker); + } for (const marker of ['Office', 'naruon', 'Yjs', 'file publication']) { expect(uml).toContain(marker); } @@ -81,6 +94,7 @@ describe('canonical product documentation graph', () => { const threatModel = repositoryFile('docs/THREAT_MODEL.md'); const testStrategy = repositoryFile('docs/TEST_STRATEGY.md'); const traceability = repositoryFile('docs/TRACEABILITY.md'); + const contracts = repositoryFile('docs/CONTRACTS.md'); expect(threatModel).toContain('clipboard'); expect(threatModel).toContain('formula'); @@ -92,6 +106,9 @@ describe('canonical product documentation graph', () => { expect(traceability).toContain('RFC 9110'); expect(traceability).toContain('WCAG 2.2'); expect(traceability).toContain('Protected `main`'); + expect(contracts).toContain('No secret'); + expect(contracts).toContain('No database'); + expect(contracts).toContain('degraded'); }); it('keeps detailed ADRs indexed and explicit about failure and rollback', () => { From 99847fc7dee5a2295f26ac2c3b053a3a95a16a80 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:30:35 +0900 Subject: [PATCH 029/101] docs: add canonical interface contract index --- docs/CONTRACTS.md | 136 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 docs/CONTRACTS.md diff --git a/docs/CONTRACTS.md b/docs/CONTRACTS.md new file mode 100644 index 00000000..30b0e8ba --- /dev/null +++ b/docs/CONTRACTS.md @@ -0,0 +1,136 @@ +# Inkspan Interface and Integration Contracts + +Status: Proposed canonical baseline + +This document is the discoverable contract index for Inkspan's public product boundaries. Protected `main` remains the implementation authority. Open pull requests may describe Proposed behavior, but they are not shipped until protected integration and exact-head acceptance. + +## Contract principles + +Inkspan owns deterministic editor state, versioned document-envelope semantics, local revision/evidence primitives, local autosave ordering, deterministic conversion, accessibility metadata, and provider-neutral adapter behavior. The embedding **host** owns transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, durable audit storage, collaboration-provider lifecycle, and model-use policy. + +Every contract is versioned or otherwise compatibility-bounded, deterministic where the domain permits it, fail closed on malformed or unsupported inputs, and explicit about degraded behavior. No contract silently promotes generated output, model output, a local digest, a browser field, a collaboration update, or a workflow status into authorization or durable-persistence authority. + +## Public package and module contract + +The root package may expose React/TipTap integration plus framework-independent helpers. Framework-independent subpaths must remain consumable without React, React DOM, TipTap UI, ProseMirror view, Yjs, browser globals, network access, database clients, credentials, or model SDKs unless that subpath's versioned contract explicitly requires them. + +Package exports, declaration files, runtime support, and packed ESM/CommonJS/strict-TypeScript consumers are release evidence. A source file being present is not sufficient proof that a public contract is packaged correctly. + +## Document envelope and revision contract + +The **document envelope** is a versioned boundary carrying schema identity and supported document content. Current-schema parsing validates strict JSON/UTF-8 and active schema requirements before canonicalization or hashing. Unknown schema migration remains host-owned. + +Canonical revision evidence is content-equality metadata only. It is not an actor identity, tenant identity, authorization grant, signature, timestamp, durable write receipt, or bearer credential. When a future identity-only migration-routing helper is implemented, it may expose bounded schema identity without becoming a permissive parser or migration executor. + +Compatibility rule: a new schema or incompatible interpretation requires an explicit new versioned contract and migration story; existing persisted semantics are not silently redefined. + +## Editor authoring contract + +Markdown/HTML authoring uses the supported TipTap/ProseMirror editor surface as the deterministic editing authority. Import/export adapters must state which constructs are supported, lossy, or rejected. Rendered or exported representations do not silently become the canonical source document. + +The editor surface may expose callbacks and handles for local state, revision capture, selection evidence, autosave coordination, and accessibility metadata. Callbacks are ordinary host code and cannot be trusted to preserve product invariants; Inkspan isolates callback failures at documented boundaries. + +## Event and evidence contract + +Local evidence records describe narrowly scoped facts such as revision identity, document transition, selection coordinates, lifecycle state, conversion warnings, or publication outcome. Evidence classes remain separate: + +- local deterministic evidence; +- workflow/check evidence; +- formal review evidence; +- host authorization evidence; +- durable persistence evidence; and +- release/publication evidence. + +No single status collapses those authorities. Ordinary evidence must avoid embedding complete document bodies, credentials, tenant identifiers, prompts, model outputs, or private exception causes unless a separate authorized contract explicitly requires them. + +## Autosave contract + +Autosave is a local coordination surface. It provides bounded single-flight ordering, bounded pending work, explicit blocked/conflict/failure state, optional lifecycle observation, and host callback handoff. The host performs authenticated transport and durable persistence. + +A server-selected strong validator is the durable concurrency authority. It advances only from a validated successful host result. Conflict, timeout ambiguity, malformed callback output, host failure, promise/reflection failure, or observer failure never fabricates durable success. + +Lifecycle observation emits only distinct externally visible document-free states. Construction and no-op operations do not manufacture events. + +Degraded behavior: when host persistence is unavailable or ambiguous, Inkspan preserves local state and explicit blocked/failure evidence rather than inventing a durable save. + +## Collaboration contract + +Inkspan collaboration is **provider-neutral**. A host may supply Yjs-compatible document, awareness, and provider bindings, but Inkspan does not own production room admission, user identity, authorization, provider credentials, reconnect policy, update persistence, retention, encryption, or durable audit. + +Collaboration document content and awareness state are untrusted tenant data. Awareness presence is not authorization. Provider outage is a host-owned degraded mode; Inkspan must not synthesize remote durability or identity from local Yjs state. + +No secret is required by the framework-independent collaboration contract itself. Provider credentials remain host-owned and must not be embedded in editor configuration or document content. + +## Naruon modular composition contract + +A naruon host may compose Inkspan through narrow `compose` / `ui.panel` integration while Inkspan remains independently usable. The host supplies serializable non-secret configuration, authenticated API transport, durable validators, provider lifecycle, tenant/document identity, accessible conflict/recovery UX, and optional model routing. + +Inkspan does not directly access a naruon application database, credential store, tenant table, message bus, or deployment control plane. Cross-document mounts require explicit host identity/state so local editor/autosave state cannot bleed between documents. + +No database is owned by this composition contract. Durable host data models and migrations stay outside Inkspan unless a future accepted ADR explicitly transfers ownership. + +## Model-assisted authoring contract + +Model-assisted authoring is separate from deterministic conversion and validation. A host may submit selected or derived context to an approved model path and receive a proposal. The proposal is untrusted content until the host/user accepts it and Inkspan's deterministic document/clipboard/conversion validators accept the resulting state. + +The host owns model/provider selection, credentials, external-data-use approval, redaction, prompt retention, model logging, tenancy, authorization, human approval, and audit. No model may authorize a save, bypass deterministic validation, or redefine a revision/durable-validator contract. + +## Deterministic Office conversion contract + +Office rendering accepts versioned bounded JSON and produces supported DOCX/XLSX/PPTX artifacts without model, network, macro, or Desktop Office dependency. Inputs must satisfy XML 1.0, size/depth/container/cycle, spreadsheet, worksheet-name, freeze-pane, supported-structure, and formula-injection rules before publication. + +File publication is explicit about overwrite semantics and uses race-safe publication behavior. Partial or failed writes are not successful artifacts. Reproducible metadata and package/document-fidelity tests define supported claims; unsupported Office constructs are rejected or documented as unsupported rather than silently approximated. + +## Security and data authority contract + +Untrusted clipboard HTML, DOM capabilities, native form values, Office structures, host callbacks, collaboration updates, and model proposals are data, not instruction or authority. Active content, external resource fetching, macros, formula execution, malicious descriptors/accessors, and malformed structures remain behind explicit fail-closed boundaries. + +No secret, credential, durable validator, tenant identifier, complete document body, or model prompt belongs in generic public diagnostics or telemetry. Hosts own authenticated transport, authorization, encryption, retention, tenant isolation, durable audit, incident response, and deployment controls. + +## Versioning and schema evolution + +Public types, schema identifiers, event/evidence shapes, package subpaths, and host integration behavior must evolve compatibly or under a new explicit version. Breaking behavior requires documented migration and rollback guidance. Unknown versions fail closed unless a specifically bounded identity-routing contract allows inspection without interpretation. + +A compatibility claim must be backed by packed-package consumers, schema fixtures, migration/rollback evidence where relevant, and the supported runtime/version matrix. + +## Failure and degraded-mode contract + +Expected degraded states are explicit rather than mapped to false success: + +- host persistence unavailable or ambiguous -> local save state remains blocked/failed; +- collaboration provider unavailable -> local editing may continue only according to host policy, with no remote-durability claim; +- unsupported or malformed document schema -> fail closed or route through an explicit host migration path; +- conversion validation/publication failure -> no successful artifact claim; +- model/provider unavailable -> deterministic authoring/conversion remains authoritative and the model proposal path is unavailable; +- review/check/release evidence missing -> merge/release remains blocked even if source-local tests pass. + +## Release and rollback contract + +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. + +Rollback must preserve readable canonical documents and must not require silently reinterpreting persisted schema semantics. Host-owned migrations, persistence rollback, tenant recovery, and deployment rollback remain host responsibilities unless a future versioned contract explicitly assigns them to Inkspan. + +## Contract-to-authority map + +| Contract surface | Inkspan authority | Host authority | +| --- | --- | --- | +| Markdown/HTML editing | deterministic editor state and supported import/export semantics | application workflow, document ownership, authorization | +| document envelope/revision | schema validation, canonical bytes, local equality evidence | migration orchestration, durable storage, signatures, tenant binding | +| 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 | +| 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 | package/artifact verification and repository evidence | downstream deployment and operational rollout | + +## Related canonical documents + +- `docs/PRD.md` — buyer/user requirements and accepted outcomes. +- `docs/TRD.md` — technical invariants and runtime boundaries. +- `ARCHITECTURE.md` — protected-main implementation architecture. +- `docs/UML.md` and `docs/DATA_MODEL.md` — interaction and conceptual data/evidence views. +- `docs/THREAT_MODEL.md` — threat analysis and trust boundaries. +- `docs/TEST_STRATEGY.md` — machine evidence required for these contracts. +- `docs/OPERABILITY.md` — failure, recovery, rollback, and incident ownership. +- `docs/TRACEABILITY.md` — standards, research, and implementation evidence traceability. +- `docs/adr/README.md` — detailed architectural decisions. From 3fc2f3dc6b10199f0b5a0cba98a8849b1f3718a8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:32:36 +0900 Subject: [PATCH 030/101] test(docs): bind contributor guidance to canonical graph --- src/canonicalProductDocumentation.test.ts | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index d8709b53..0ddb7241 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -7,6 +7,11 @@ const repositoryFile = (path: string): string => readFileSync(resolve(process.cwd(), path), 'utf8'); const requiredFiles = [ + 'AGENTS.md', + 'CLAUDE.md', + 'ARCHITECTURE.md', + 'CHANGELOG.md', + 'docs/README.md', 'docs/PRD.md', 'docs/TRD.md', 'docs/CONTRACTS.md', @@ -36,6 +41,35 @@ describe('canonical product documentation graph', () => { } }); + it('keeps contributor guidance aligned with the canonical documentation spine', () => { + const agents = repositoryFile('AGENTS.md'); + const claude = repositoryFile('CLAUDE.md'); + const index = repositoryFile('docs/README.md'); + + for (const document of [agents, claude]) { + expect(document).toContain('docs/README.md'); + expect(document).toContain('Protected `main`'); + expect(document).toContain('docs/PRD.md'); + expect(document).toContain('docs/TRD.md'); + expect(document).toContain('docs/CONTRACTS.md'); + } + for (const marker of [ + '../ARCHITECTURE.md', + 'PRD.md', + 'TRD.md', + 'CONTRACTS.md', + 'UML.md', + 'DATA_MODEL.md', + 'THREAT_MODEL.md', + 'TEST_STRATEGY.md', + 'OPERABILITY.md', + 'TRACEABILITY.md', + 'adr/README.md', + ]) { + expect(index).toContain(marker); + } + }); + it('records host ownership and deterministic Inkspan authority consistently', () => { const prd = repositoryFile('docs/PRD.md'); const trd = repositoryFile('docs/TRD.md'); From fea77f26d62651ff9bda3b0cd0e3e84ae7b62929 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:32:53 +0900 Subject: [PATCH 031/101] docs: add canonical documentation index --- docs/README.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..f2181015 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,47 @@ +# Inkspan canonical documentation + +Status: Proposed canonical baseline + +This directory is the discoverable index for Inkspan's product, technical, security, operability, and architecture records. Protected `main` is the implementation authority. Proposed or active-PR behavior must remain labeled as such until it reaches protected `main` with the required evidence. + +## Canonical graph + +| Document | Authority | +| --- | --- | +| [`../ARCHITECTURE.md`](../ARCHITECTURE.md) | Current protected-main implementation architecture and bounded-context ownership | +| [`PRD.md`](PRD.md) | Product users, jobs, buyer outcomes, non-goals, acceptance and claim boundaries | +| [`TRD.md`](TRD.md) | Technical invariants, runtime boundaries, failure semantics and release evidence | +| [`CONTRACTS.md`](CONTRACTS.md) | Public package/API/event/schema/plugin/collaboration and host-integration contracts | +| [`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 | +| [`TEST_STRATEGY.md`](TEST_STRATEGY.md) | Unit/integration/browser/Office/security/accessibility/package evidence strategy | +| [`OPERABILITY.md`](OPERABILITY.md) | Failure handling, recovery, incident ownership, rollback and release operations | +| [`TRACEABILITY.md`](TRACEABILITY.md) | Requirements/standards/research-to-decision/test evidence traceability | +| [`adr/README.md`](adr/README.md) | Status-bearing architectural decision index | + +The root `SECURITY.md` is the disclosure-policy authority once that separately owned bounded change reaches protected `main`; this index must not duplicate or race an active security-policy branch. `CHANGELOG.md` records shipped/reviewable change history, while `AGENTS.md` and `CLAUDE.md` point contributors back to this canonical graph rather than becoming parallel architecture specifications. + +## Status discipline + +Use these terms consistently: + +- **Implemented on protected main** — code and behavior exist on the current protected branch and have applicable acceptance evidence. +- **Active PR / Proposed** — reviewable work exists but is not shipped authority. +- **Accepted architecture** — a durable decision is approved by the governing ADR but implementation may still be incomplete. +- **Planned** — bounded future work with no protected implementation claim. +- **Research only** — evidence or alternatives under evaluation, not a product commitment. +- **Superseded** — retained only for history; a newer decision or implementation is authoritative. +- **Out of scope** — deliberately excluded from Inkspan ownership. + +Never use a PR body, check status, model verdict, local test, or conversation as a substitute for protected-main implementation authority. + +## Ownership boundary + +Inkspan owns deterministic editor/conversion behavior, versioned document/evidence contracts, local autosave coordination, accessibility metadata, package behavior, and provider-neutral adapters. The embedding host owns authenticated transport, authorization, tenant isolation, durable persistence, credentials, migration execution, retention, deployment, durable audit, collaboration-provider authority, and model-use policy unless a future accepted versioned contract explicitly changes that division. + +## Change discipline + +A material contract change should update the smallest affected set of PRD/TRD/CONTRACTS/Architecture/ADR/UML/data-model/security/test/operability/traceability records and corresponding machine-checkable documentation contracts. If a document is unaffected, preserve it rather than performing churn solely for consistency optics. + +Stable architectural documents should avoid embedding transient PR heads, workflow run IDs, or temporary provider states. Put dated operational evidence in bounded doctoring/evidence records instead. From cbae8c722b0dcbf1189d26148bd0facf766fe53d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:33:08 +0900 Subject: [PATCH 032/101] docs: align Claude guidance with canonical architecture --- CLAUDE.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..de8315c7 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,34 @@ +# CLAUDE.md + +## Repository authority + +Protected `main` is Inkspan's implementation authority. Start architecture, product, interface, security, testing, and operability work from the canonical graph in `docs/README.md`; in particular, keep `docs/PRD.md`, `docs/TRD.md`, and `docs/CONTRACTS.md` aligned with shipped behavior and accepted ADRs rather than reconstructing product intent from conversations or pull-request prose. + +## Product boundary + +Inkspan owns deterministic Markdown/HTML authoring and conversion behavior, versioned document/evidence contracts, local autosave coordination, accessibility metadata, package behavior, and provider-neutral adapters. The embedding host owns authenticated transport, authorization, tenant isolation, durable persistence, credentials, migration execution, retention, deployment, durable audit, collaboration-provider authority, and model-use policy unless an accepted versioned contract explicitly changes that boundary. + +Keep deterministic conversion separate from model-assisted authoring. Model output is an untrusted proposal and cannot bypass editor/document/clipboard/Office validation, host authorization, user approval, or durable concurrency controls. + +## Security and reliability invariants + +- Preserve strict fail-closed handling for untrusted clipboard HTML, links, image sources, document envelopes, Office structures, host callbacks, collaboration updates, and model proposals. +- Office rendering remains network-free, macro-free, model-free, Desktop-Office-free, bounded, formula-injection-safe, and race-safe at publication. +- Local SHA-256 document revisions are equality evidence, not authorization, signatures, tenant identity, server time, or durable-write receipts. +- Host/server-selected strong validators remain the durable compare-and-swap authority. +- Do not place credentials, complete document bodies, tenant identifiers, prompts/model output, durable validators, or private exception causes into generic diagnostics or telemetry. +- Do not move transport, persistence, tenancy, credential, retention, provider, or deployment ownership into Inkspan merely to make a local feature or test easier. + +## Change and evidence discipline + +Use test-first changes for product behavior and permanent contracts where practical. Preserve exact owned production statement/branch/function/line coverage and public-docstring requirements enforced by repository CI. Validate public package behavior from packed artifacts, not source imports alone. + +For architectural changes, update the smallest affected canonical records and ADRs. Keep status language explicit: implemented on protected main, active PR/proposed, accepted architecture, planned, research only, superseded, or out of scope. + +A queued, pending, cancelled, skipped-required, stale-head, predecessor-head, status-only, comment-only, author-only, or synthetic-merge result is not acceptance evidence. Formal review, automated review, repository checks, host authorization, and release evidence remain distinct authorities. + +## Integration discipline + +Inkspan must remain independently usable. naruon and other CWL hosts compose it through narrow host-owned boundaries; they are not required runtime dependencies. Central `.github`, contextual-orchestrator, and other repositories are external bounded contexts and must not be locally patched around when they own a shared control-plane defect. + +Before changing public behavior, inspect `docs/README.md`, `docs/PRD.md`, `docs/TRD.md`, `docs/CONTRACTS.md`, `ARCHITECTURE.md`, the relevant ADRs, and current tests. Prefer the smallest root-cause-changing change with explicit rollback and compatibility evidence. From fdd55684436e93857a7544e3eea52b782ca286e1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:33:18 +0900 Subject: [PATCH 033/101] docs: align agent guidance with canonical product graph --- AGENTS.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 1de8ae17..729ae2d8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,13 @@ # AGENTS.md +## Canonical product and architecture authority + +Protected `main` is Inkspan's implementation authority. Before changing product behavior, public contracts, architecture, security boundaries, tests, release behavior, or integration guidance, start from `docs/README.md` and keep `docs/PRD.md`, `docs/TRD.md`, and `docs/CONTRACTS.md` aligned with the current implementation and accepted ADRs. + +Inkspan owns deterministic editor/conversion behavior, versioned document/evidence contracts, local autosave coordination, accessibility metadata, package behavior, and provider-neutral adapters. Hosts retain transport, authentication, authorization, tenant isolation, durable persistence, credentials, migration execution, retention, deployment, durable audit, collaboration-provider authority, and model-use policy unless an accepted versioned contract explicitly changes that boundary. + +Do not infer shipped behavior from conversation history, PR bodies, model output, or predecessor-head evidence. Keep Proposed/Active-PR behavior distinct from implementation on Protected `main`, preserve fail-closed security and deterministic conversion boundaries, and update the smallest affected canonical documents plus tests when a durable contract changes. + ## Code-owner review gates — disabled (on hold) As of 2026-08-04, code-owner review requirements (`require_code_owner_reviews` in branch From 728f4e7c4dd832a9c7c93831aab0d46fc782f465 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:37:10 +0900 Subject: [PATCH 034/101] test(docs): require complete ADR decision records --- src/canonicalProductDocumentation.test.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index 0ddb7241..092bf741 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -145,7 +145,7 @@ describe('canonical product documentation graph', () => { expect(contracts).toContain('degraded'); }); - it('keeps detailed ADRs indexed and explicit about failure and rollback', () => { + it('keeps detailed ADRs indexed and complete enough for acquisition review', () => { const index = repositoryFile('docs/adr/README.md'); for (const path of requiredFiles.filter((path) => /docs\/adr\/\d{4}-/.test(path))) { @@ -153,12 +153,19 @@ describe('canonical product documentation graph', () => { expect(filename).toBeDefined(); expect(index).toContain(filename!); const adr = repositoryFile(path); - expect(adr).toContain('## Context'); - expect(adr).toContain('## Decision'); - expect(adr).toContain('## Consequences'); - expect(adr).toContain('## Failure and recovery'); - expect(adr).toContain('## Verification'); - expect(adr).toContain('## Rollback or supersession'); + for (const heading of [ + '## Context', + '## Alternatives considered', + '## Decision', + '## Consequences', + '## Failure and recovery', + '## Security and privacy impact', + '## Compatibility and migration', + '## Verification', + '## Rollback or supersession', + ]) { + expect(adr).toContain(heading); + } } }); }); From 5d40d6012907d7e6b360d21697d396a7b7f329de Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:38:07 +0900 Subject: [PATCH 035/101] docs(adr): complete host-authority decision record --- docs/adr/0001-product-host-authority.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0001-product-host-authority.md b/docs/adr/0001-product-host-authority.md index 115c647f..975f4c58 100644 --- a/docs/adr/0001-product-host-authority.md +++ b/docs/adr/0001-product-host-authority.md @@ -6,6 +6,12 @@ Status: Proposed Inkspan must work as a standalone authoring/conversion product and as a module inside naruon or another CWL host. Mixing host transport, tenant, identity, persistence, credential, deployment, retention, audit, or model-routing authority into the editor package would make standalone use harder and create hidden security coupling. +## Alternatives considered + +- Let Inkspan own transport, persistence, tenancy, credentials, and collaboration-provider lifecycle. Rejected because it creates hidden privilege and makes independent package use depend on one deployment architecture. +- Provide separate standalone and CWL-host product forks. Rejected because duplicated implementations would drift on document, conversion, and security semantics. +- Keep Inkspan deterministic and capability-bounded while hosts inject explicitly owned services. Selected because it preserves standalone reuse and makes authority reviewable at integration boundaries. + ## Decision Inkspan owns deterministic editor, conversion, canonical envelope, local evidence, local autosave ordering, accessibility metadata, package, and provider-neutral adapter behavior. Hosts own transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, durable audit storage, collaboration-provider lifecycle, and model-use policy. @@ -18,6 +24,14 @@ The same package can be embedded or used independently. Host failures remain exp If an Inkspan change begins to create network providers, choose tenants, store secrets, authorize model calls, or claim durable persistence success, fail the architecture contract and revert the authority expansion. Host integration defects are repaired at the host boundary rather than by granting Inkspan broader privilege. +## Security and privacy impact + +Least privilege is explicit: Inkspan receives only capabilities necessary for deterministic local behavior and does not acquire tenant credentials or durable authorization authority. Document bodies and host-confidential metadata remain subject to host purpose, access, encryption, logging, retention, and deletion policy rather than being copied into a new Inkspan control plane. + +## Compatibility and migration + +Existing standalone package consumers require no host service. Host integrations evolve additively through explicit capabilities and versioned public contracts. Any future transfer of persistence, tenant, credential, provider, or deployment ownership into Inkspan is a breaking architecture change requiring an accepted ADR, migration and rollback plan, revised threat model, and compatibility evidence for standalone consumers. + ## Verification Canonical Architecture/PRD/TRD ownership language, integration tests, package-consumer isolation, provider-neutral collaboration tests, and documentation contracts must agree. Protected `main` remains the implementation authority. From bedb2344da42e380faa049ca8925418613f5e61a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:38:24 +0900 Subject: [PATCH 036/101] docs(adr): complete document-authority decision record --- docs/adr/0002-document-revision-authority.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0002-document-revision-authority.md b/docs/adr/0002-document-revision-authority.md index 2d6b5b0c..15a68373 100644 --- a/docs/adr/0002-document-revision-authority.md +++ b/docs/adr/0002-document-revision-authority.md @@ -6,6 +6,12 @@ Status: Proposed Inkspan needs deterministic document persistence/export and local equality evidence without turning a content digest into authorization, identity, or durable concurrency authority. +## Alternatives considered + +- Use editor-local JSON or rendered HTML directly as durable identity. Rejected because semantically equivalent values can serialize differently and because rendered output is not the canonical source authority. +- Treat a SHA-256 content digest as the durable concurrency token. Rejected because a client-derived digest does not prove the server's current durable representation or authorization state. +- Use a versioned canonical envelope for local equality and a host/server-selected validator for durable concurrency. Selected because it separates deterministic content identity from durable authority. + ## Decision A versioned validated `document_envelope` is the canonical document value. Strict JSON/UTF-8 handling and bounded validation precede canonicalization. SHA-256 revision evidence is derived from the exact canonical envelope and is equality evidence only. Durable compare-and-swap uses a host/server-selected strong validator under RFC 9110 semantics. @@ -18,6 +24,14 @@ Local restore, transition, and selection evidence can bind to exact content with Malformed, ambiguous, over-limit, unsupported, or hostile envelope input fails closed with bounded diagnostics. If local state moves during asynchronous evidence capture, the operation returns no stale claim. Durable ambiguity is reconciled by the host; a local digest never advances durable state. +## Security and privacy impact + +Canonicalization and revision derivation operate without granting network, tenant, credential, or persistence authority. Revision values can still be tenant-confidential correlation metadata, so they must not be exposed as public high-cardinality telemetry or treated as bearer capabilities. Ordinary evidence avoids duplicating complete document bodies. + +## Compatibility and migration + +Envelope schema identifiers and versions are explicit compatibility boundaries. Existing revision values must remain stable for the same accepted canonical contract. Unsupported legacy/future versions route through host-owned migration rather than being interpreted by the current parser. Any canonicalization or digest change requires a new versioned contract, compatibility fixtures, migration guidance, and rollback evidence. + ## Verification Envelope parsing/canonicalization/UTF-8/resource-limit regressions, revision/transition/selection tests, packed consumer tests, and RFC 9110/JCS documentation must remain coherent. From 3566061c2dd4f6a9c38d01b215cccdf1cd776651 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:38:48 +0900 Subject: [PATCH 037/101] docs(adr): complete clipboard-security decision record --- docs/adr/0003-safe-rich-clipboard.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0003-safe-rich-clipboard.md b/docs/adr/0003-safe-rich-clipboard.md index d9b928db..2b235f53 100644 --- a/docs/adr/0003-safe-rich-clipboard.md +++ b/docs/adr/0003-safe-rich-clipboard.md @@ -6,6 +6,12 @@ Status: Proposed Rich clipboard HTML is attacker-controlled browser input. A sanitizer that is correct only as a pure helper but is not installed in the real TipTap/ProseMirror paste pipeline does not protect the product. Browser fragment parsing can also differ across Chromium, Firefox, and WebKit. +## Alternatives considered + +- Accept browser/TipTap parsing with only downstream rendering controls. Rejected because active, hidden, resource-bearing, or malformed content can enter editor state before later controls run. +- Sanitize only through a standalone helper that hosts may call. Rejected because omission or wrong pipeline ordering would leave the default editor path unprotected. +- Install one bounded semantic sanitizer in the real paste pipeline while retaining the pure API and cross-engine verification. Selected because it binds the trust boundary to actual editor behavior and preserves deterministic direct use. + ## Decision Sanitize untrusted rich HTML through a bounded, fail-closed semantic allowlist installed in the actual TipTap/ProseMirror paste pipeline. The sanitizer performs no external fetch or active execution, rejects unsupported active/resource-bearing structures, applies resource ceilings, and keeps its pure API behavior aligned with editor integration. Browser-engine differential evidence is required before the rich-clipboard release line is published. @@ -18,6 +24,14 @@ Supported semantic formatting can survive paste while active or hidden content i Malformed input, hostile DOM capabilities, reflection failures, over-limit input, or unsafe structures fail closed with bounded diagnostics. If a security-relevant engine difference is found, add it to the differential corpus and repair the sanitizer or explicitly document a standards-grounded safe difference. Do not broaden the allowlist merely to recover parity. +## Security and privacy impact + +The boundary reduces active-content, external-resource, hidden-content, parser-confusion, and denial-of-service risk before clipboard content becomes editor state. It performs no network request, executes no embedded script, exposes no credential, and must not copy rejected source payloads or private exception causes into public diagnostics. Host CSP, tenant authorization, downstream rendering, and external egress policy remain independent controls. + +## Compatibility and migration + +This boundary may intentionally remove HTML constructs that were previously accepted by permissive paste behavior, so the default rich-paste change is a release-significant compatibility decision. Supported semantic constructs and any engine-specific safe differences are versioned through tests/documentation. Rollout requires browser-differential evidence; rollback may disable the rich transform or return to a narrower plain/supported-content path without accepting arbitrary HTML. + ## Verification Use sanitizer unit tests, actual editor paste-pipeline integration tests, hostile DOM/reflection cases, package consumers, security scans, and the dependency-locked Chromium/Firefox/WebKit differential release gate tracked by the rich-clipboard assurance issue. From efd8d262557e60c05004671289b5ea0d1bb0b819 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:39:28 +0900 Subject: [PATCH 038/101] docs(adr): complete autosave decision record --- docs/adr/0004-durable-validator-autosave.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/adr/0004-durable-validator-autosave.md b/docs/adr/0004-durable-validator-autosave.md index 1eeca01e..35cd42b3 100644 --- a/docs/adr/0004-durable-validator-autosave.md +++ b/docs/adr/0004-durable-validator-autosave.md @@ -6,6 +6,13 @@ Status: Proposed Local editor revisions are useful equality evidence but cannot prove a durable server write. Autosave also must avoid concurrent duplicate writes, unbounded queued work, silent conflict recovery, and telemetry callbacks that alter persistence behavior. +## Alternatives considered + +- Overlapping saves for every local edit: rejected because ordering and retained work become ambiguous. +- A client content digest as the durable validator: rejected because local equality evidence is not durable server authority. +- An unbounded FIFO of every intermediate revision: rejected because memory and write volume grow without a fixed ceiling. +- One active save plus one replaceable pending revision, with explicit blocked recovery and a host/server-selected strong validator: selected. + ## Decision Use a single-flight autosave queue with bounded active/pending work and explicit `idle`, `saving`, `blocked`, `closing`, and `closed` lifecycle state. A durable session accepts and advances only host/server-selected strong HTTP entity tags for compare-and-swap. Conflict or ambiguous save failure blocks progression until explicit recovery. Optional lifecycle observation emits only distinct document-free transitions; construction and no-op operations emit nothing, and observer exceptions are isolated. @@ -18,6 +25,14 @@ Inkspan can coordinate deterministic local ordering while the host remains the o Malformed or weak validators fail closed. Conflict preserves durable uncertainty and requires authenticated host recovery. Ambiguous transport failure never advances the validator. Recovery with no pending work may return to idle; unsuccessful/no-op recovery does not synthesize an observer event. Closing waits only for bounded retained work. +## Security and privacy impact + +Autosave coordination does not grant authorization or tenant authority. Strong validators and local revisions can be tenant-confidential equality metadata, so snapshots and public diagnostics remain document-free and must not expose validators, credentials, complete document bodies, or private callback failures. + +## Compatibility and migration + +The public queue/session states, validator grammar, and result contracts are compatibility surfaces. Hosts adopting the durable session supply a valid server-selected strong validator and keep durable retry/conflict policy. Any future lifecycle-state or retention change requires compatibility tests, migration guidance, and a rollback that preserves host durable state. + ## Verification Queue/session state-machine tests, no-op observation regressions, callback-failure isolation, validator grammar tests, concurrency/flush/close regressions, packed ESM/CommonJS/strict-TypeScript consumers, and exact-head coverage/security gates verify the contract. From 357d8f3fcc20271712292637b78ac30d00502ab3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:39:47 +0900 Subject: [PATCH 039/101] docs(adr): complete revision-evidence decision record --- docs/adr/0005-revision-scoped-review-evidence.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0005-revision-scoped-review-evidence.md b/docs/adr/0005-revision-scoped-review-evidence.md index 9abc5605..8dfa121d 100644 --- a/docs/adr/0005-revision-scoped-review-evidence.md +++ b/docs/adr/0005-revision-scoped-review-evidence.md @@ -6,6 +6,12 @@ Status: Proposed Delayed review, annotation, AI assistance, and audit-like workflows need to refer to an exact editor state. Copying selected text or entire document bodies into ordinary metadata increases privacy exposure, while asynchronous hashing can accidentally bind coordinates to a later document if state is reread. +## Alternatives considered + +- Store selected text or full documents in ordinary review metadata. Rejected because it duplicates sensitive content and still does not guarantee stable anchoring after edits. +- Capture coordinates first and reread the document later for hashing. Rejected because asynchronous work can bind coordinates and revision to different editor states. +- Capture structural coordinates and canonical content from one immutable editor snapshot, then derive minimum revision-scoped evidence. Selected because it preserves temporal consistency while minimizing disclosure. + ## Decision Capture selection coordinates and the canonical document envelope from the same immutable editor state before asynchronous revision derivation. Transition evidence validates previous and resulting envelopes before deriving both revisions. Evidence contains only the minimum revision/coordinate/change metadata required by the versioned contract and excludes document bodies, actor, tenant, time, authorization, model identity, transport result, signature, and durable-write claims. @@ -18,6 +24,14 @@ Hosts can detect stale review coordinates and content transitions without duplic If editor state changes during a capture boundary, the API must not emit a stale mixed-state claim. Coordinates are valid only with the matching revision. A changed document requires an explicit host re-anchor, compare, merge, fork, or collaborative anchoring policy. +## Security and privacy impact + +Ordinary evidence is deliberately content-minimized and does not synthesize actor, tenant, model, authorization, signature, or durable-save claims. Revision identifiers and structural coordinates can still correlate tenant activity, so hosts must treat them as purpose-bound metadata and avoid public high-cardinality telemetry or unauthenticated disclosure. + +## Compatibility and migration + +Evidence shape and coordinate semantics are versioned contracts. Existing evidence remains meaningful only against its exact revision. A future durable/collaborative anchor format requires an explicit new version or migration rule; old coordinates must not be silently reinterpreted against a new document generation. + ## Verification Use concurrency tests, range/caret cases, transition ordering tests, recursive document-content absence checks, frozen-output checks, packed ESM/CommonJS/strict-TypeScript consumers, and exact-head coverage/security gates. From b67f8d1a016b380ec6b3b110523d1d5c22ee2b14 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:40:14 +0900 Subject: [PATCH 040/101] docs(adr): complete SSR form decision record --- docs/adr/0006-ssr-native-form-boundary.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/adr/0006-ssr-native-form-boundary.md b/docs/adr/0006-ssr-native-form-boundary.md index 9a59fef0..14573a8a 100644 --- a/docs/adr/0006-ssr-native-form-boundary.md +++ b/docs/adr/0006-ssr-native-form-boundary.md @@ -6,6 +6,13 @@ Status: Proposed Inkspan must support server-rendered shells and optional native form integration without instantiating a browser editor on the server or treating a hidden field as trusted server state. Hydration must not lose the chosen initial value, and form serialization must stay synchronized once the editor becomes authoritative. +## Alternatives considered + +- Construct TipTap/ProseMirror during server rendering. Rejected because editor-view behavior depends on browser/DOM capabilities and risks hydration divergence. +- Treat the native form field as a durable/authenticated document channel. Rejected because browser-controlled fields are untrusted request input. +- Omit all native-form support. Rejected because standards-based host forms benefit from an optional synchronized submission surface. +- Emit an escaped client-controlled field only when explicitly enabled, then mirror editor transactions after hydration. Selected. + ## Decision Server rendering never constructs a TipTap/ProseMirror editor view. When `formFieldName` is explicitly enabled, Inkspan emits the selected controlled Markdown/HTML serialization as an escaped read-only native input value through SSR and matching hydration. Once the editor is authoritative, document transactions synchronously mirror the current serialization into the native field. The submitted value is client-controlled input only. @@ -18,6 +25,14 @@ SSR hosts can participate in native form flows while preserving hydration contin Invalid or stale client values never become authorization or durable evidence. Native resets cannot silently desynchronize a configured field from an editor the host intentionally retains. If SSR/form integration proves unsafe for a host, omit the field and use an explicit host transport after independent server validation. +## Security and privacy impact + +The native field is intentionally treated as attacker-controlled request data. Inkspan escapes serialized content and does not assign authentication, CSRF, tenant, signature, integrity, or durable-write authority to it. Because enabling the field can place the document body in HTML/form submission, hosts with stricter disclosure or retention requirements must opt out and use their own authorized transport. + +## Compatibility and migration + +`formFieldName` remains opt-in, so existing consumers keep their current transport behavior. Hosts adopting it must validate and authorize the submitted value exactly as any other client input. Future changes to field naming, serialization mode, hydration, or reset semantics require SSR/hydration compatibility tests and migration guidance; rollback is to remove the optional field without changing canonical document semantics. + ## Verification Use `renderToString`/SSR tests, controlled-over-default precedence, escaping cases, hydration continuity, synchronous transaction-to-`FormData` tests, reset behavior, opt-out non-disclosure, no server editor construction, and documentation contracts. From 603d14d1e49827be2fbfc395588f8a895a92f94b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:40:34 +0900 Subject: [PATCH 041/101] docs(adr): complete collaboration decision record --- docs/adr/0007-provider-neutral-collaboration.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0007-provider-neutral-collaboration.md b/docs/adr/0007-provider-neutral-collaboration.md index 8831701f..1bbda8be 100644 --- a/docs/adr/0007-provider-neutral-collaboration.md +++ b/docs/adr/0007-provider-neutral-collaboration.md @@ -6,6 +6,12 @@ Status: Proposed Inkspan needs collaborative editing compatibility without choosing a network provider, room identity, tenant authority, credential, persistence store, retention policy, or audit system. Coupling those responsibilities to the editor would make standalone operation weaker and create hidden privilege. +## Alternatives considered + +- Bundle a specific collaboration service/provider into Inkspan. Rejected because transport credentials, tenant admission, retention, reconnect policy, and deployment would become hidden editor responsibilities. +- Let Inkspan create and destroy host providers automatically. Rejected because a provider may be shared across product surfaces and its lifecycle belongs to the host. +- Accept host-supplied Yjs-compatible document/awareness bindings and keep provider lifecycle external. Selected because it preserves provider neutrality and standalone operation. + ## Decision Inkspan may bind editor state to host-supplied Yjs-compatible document and awareness surfaces. The host creates, authenticates, authorizes, monitors, reconnects, persists, expires, and destroys the collaboration provider. Inkspan does not create or destroy that provider and does not interpret awareness or update receipt as authorization or durable persistence evidence. @@ -18,6 +24,14 @@ Standalone and enterprise hosts can select their own collaboration transport and Provider outage, authorization failure, room loss, or awareness-policy failure is surfaced to the host. The host decides whether the editor remains locally writable, becomes read-only, reconnects, forks, or blocks. Detaching Inkspan must not destroy a provider shared with other product surfaces or erase the host-owned Yjs document. +## Security and privacy impact + +Yjs updates and awareness metadata are untrusted tenant data and can contain sensitive content or presence information. They are never treated as authorization, tenant admission, or durable-write proof. Provider credentials, room keys, retention, encryption, logging, and awareness-disclosure policy remain host-owned and must not be embedded in document or editor configuration intended for generic diagnostics. + +## Compatibility and migration + +The collaboration entrypoint stays optional and must not make Yjs/provider dependencies mandatory for standalone non-collaborative consumers. Hosts may migrate providers without changing Inkspan document semantics when they preserve the supplied Yjs-compatible contract. Any future Inkspan-owned transport/provider requires a breaking versioned contract, threat review, migration/rollback plan, and preserved standalone mode. + ## Verification Use provider-neutral integration tests with supplied Yjs state, lifecycle/remount tests, awareness non-authority/privacy contracts, package-dependency checks, and architecture documentation tests. No test should require a production provider credential or network connection to prove the adapter contract. From aad566d6224b464a1b2b38520171c026239c4bad Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:40:54 +0900 Subject: [PATCH 042/101] docs(adr): complete Office-renderer decision record --- docs/adr/0008-deterministic-office-rendering.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0008-deterministic-office-rendering.md b/docs/adr/0008-deterministic-office-rendering.md index e0fea8ff..2ecfc99d 100644 --- a/docs/adr/0008-deterministic-office-rendering.md +++ b/docs/adr/0008-deterministic-office-rendering.md @@ -6,6 +6,12 @@ Status: Proposed Enterprise buyers need DOCX, XLSX, and PPTX output that is reproducible and testable without model inference, Desktop Office automation, macros, or hidden network access. Office formats also introduce formula injection, XML/package validity, resource exhaustion, and file-publication hazards. +## Alternatives considered + +- Automate Desktop Office/LibreOffice during production rendering. Rejected because it adds desktop-runtime, macro, platform, and hidden-network authority and weakens deterministic packaging. +- Let an LLM emit Office XML/packages directly. Rejected because output structure and safety would become model-dependent and difficult to bound or reproduce. +- Render a strict versioned JSON-compatible request through bounded local libraries and explicit publication semantics. Selected because it keeps supported fidelity testable and deterministic. + ## Decision The Office renderer consumes a strict versioned JSON-compatible contract and produces deterministic DOCX/XLSX/PPTX artifacts locally. It is network-free, macro-free, model-free, and Desktop-Office-free. Validate XML 1.0 content, resource/container/depth limits, worksheet names, freeze panes, supported structures, and spreadsheet formula-injection boundaries before successful publication. Output publication is race-safe with explicit overwrite semantics. @@ -18,6 +24,14 @@ Rendering remains independently deployable and auditable. Fidelity claims are li Invalid or unsupported input fails closed with bounded diagnostics. Partial or failed output is not successful evidence and must not replace unrelated files. A caller requesting overwrite does so explicitly. Recovery rebuilds from the exact validated source rather than editing a partially generated package. +## Security and privacy impact + +The renderer does not fetch external resources, execute macros, invoke a model, or require Desktop Office. Spreadsheet strings are neutralized according to the supported literal-text contract so untrusted content cannot silently become a formula. Bounded validation reduces XML/package and resource-exhaustion risk. Callers still own authorization, storage location, document classification, retention, distribution, and downstream-viewer policy. + +## Compatibility and migration + +Supported DOCX/XLSX/PPTX constructs and the JSON request schema are explicit compatibility surfaces. New structures require schema/version updates and real document-fidelity fixtures; unsupported constructs must not be silently advertised as lossless. Python runtime/package support must remain aligned across metadata, CI, README, wheel evidence, and release guidance. Rollback restores the last verified renderer contract and rebuilds artifacts from source. + ## Verification Run supported Python-version tests, exact statement/branch coverage, complete public docstrings, realistic DOCX/XLSX/PPTX package inspection, formula-prefix regressions, XML-invalid character cases, cyclic/depth/container limits, worksheet/freeze-pane cases, publication-race tests, wheel/package inspection, license checks, and deterministic digest/evidence checks where applicable. From 1312f58b3994df63792940ec652e1447bbce5a9c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:41:14 +0900 Subject: [PATCH 043/101] docs(adr): complete naruon composition decision record --- docs/adr/0009-naruon-modular-composition.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0009-naruon-modular-composition.md b/docs/adr/0009-naruon-modular-composition.md index 0e4a6f14..8ccb80f5 100644 --- a/docs/adr/0009-naruon-modular-composition.md +++ b/docs/adr/0009-naruon-modular-composition.md @@ -6,6 +6,12 @@ Status: Proposed CWL hosts need to compose Inkspan through naruon `compose` / `ui.panel` surfaces while standalone adopters must not acquire a naruon or contextual-orchestrator dependency. SSR, autosave, collaboration, model use, and durable storage also have distinct authority boundaries that must not collapse inside a panel component. +## Alternatives considered + +- Make naruon a required Inkspan runtime dependency. Rejected because standalone consumers would inherit host-specific transport, tenancy, and release coupling. +- Let Inkspan call contextual-orchestrator, host APIs, persistence, or provider services directly. Rejected because host credentials and authorization boundaries would move into the editor package. +- Keep integration additive through a narrow host-owned client/panel boundary with serializable non-secret configuration. Selected because Inkspan remains independently usable while CWL hosts share composition conventions. + ## Decision Naruon integration is additive and host-owned. A naruon host mounts Inkspan through a narrow client boundary, passes only serializable non-secret configuration, owns authenticated API calls and strong durable validators, owns Yjs provider lifecycle, and optionally routes model assistance through contextual-orchestrator under host policy. Inkspan retains deterministic editor/conversion/evidence authority and does not import host control-plane authority. @@ -18,6 +24,14 @@ Inkspan remains independently usable and testable, while CWL products can share A host must issue a fresh editing-context identity when switching authorized documents so local queue/editor state cannot bleed across documents. Provider or model outages are host-degraded modes. A central `.github`, naruon, or contextual-orchestrator defect is treated as a read-only dependency; Inkspan continues independent work rather than weakening local safety gates. +## Security and privacy impact + +Only non-secret serializable configuration crosses the generic composition boundary. Authentication tokens, tenant authority, durable validators, provider credentials, model credentials, retention policy, and durable audit remain host-owned. Cross-document remount identity prevents local editor/autosave state from being reused as implicit authorization for another host document. + +## Compatibility and migration + +Standalone exports remain usable without naruon or contextual-orchestrator. Host-specific composition evolves through versioned/narrow adapters rather than changing Inkspan's canonical document semantics. A host migration may replace API, provider, or model infrastructure while preserving the documented capability contract; rollback detaches the host adapter without rewriting Inkspan documents. + ## Verification Use `ARCHITECTURE.md`, `docs/naruon-compose-ui-panel.md`, architecture documentation tests, SSR/client-boundary tests, autosave validator/recovery tests, host-provider lifecycle tests, and packed standalone consumers proving no required naruon/contextual-orchestrator dependency. From 5d28d356af729ceaaa38da807ee64bbe1a6c47ad Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:42:53 +0900 Subject: [PATCH 044/101] docs(adr): complete release-evidence decision record --- docs/adr/0010-release-evidence-authority.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/adr/0010-release-evidence-authority.md b/docs/adr/0010-release-evidence-authority.md index 9c266e9a..96469aaa 100644 --- a/docs/adr/0010-release-evidence-authority.md +++ b/docs/adr/0010-release-evidence-authority.md @@ -6,6 +6,12 @@ Status: Proposed Inkspan releases combine JavaScript/TypeScript packages, Office Python artifacts, checksums, SBOM/provenance, exact-head CI/security evidence, and repository review/protection state. Stale draft assets or predecessor-head checks can look healthy while referring to different source. +## Alternatives considered + +- Publish best-effort artifacts whenever local builds appear green. Rejected because local or predecessor evidence can refer to a different source generation and does not prove remote artifact integrity or repository-policy acceptance. +- Reuse or repair mutable draft-release assets opportunistically. Rejected because stale/unexpected assets and digest drift can be mistaken for the intended exact-source release. +- Bind publication to one exact integrated protected head and fail closed on evidence or inventory ambiguity. Selected because source, review, provenance, and artifact authority remain reconstructable for operators and buyers. + ## Decision Release authority exists only for one exact integrated protected head. The release process verifies the expected local and remote artifact inventory and digests, package-consumer evidence, supported runtime matrix, applicable security/coverage/accessibility gates, SBOM/provenance, unresolved review findings, formal review requirements, and repository protection. Stale, unexpected, incomplete, or digest-mismatched draft assets fail closed and are not silently deleted or reused. Comments, model prose, status-only signals, predecessor evidence, or author assertions are not substitutes for formal approval where policy requires it. @@ -18,6 +24,14 @@ Publication is slower than a best-effort upload but produces acquisition-reviewa If artifact inventory, digest, provenance, review, or exact-head evidence is ambiguous, stop publication. Repair the source or release workflow, regenerate evidence from the exact head, and resume only through a contract that proves the existing remote draft is exactly expected. A bad published release is corrected through a new verified release or supported withdrawal/yank process. +## Security and privacy impact + +Release credentials remain least-privilege workflow authority and are not product runtime credentials. Artifact integrity, provenance, and exact-source binding reduce supply-chain substitution risk. Release logs, SBOM/provenance records, and packaged artifacts must not accidentally include tenant documents, prompts/model outputs, host credentials, private validators, or unrelated secrets. Review or approval authority is never synthesized from a bot comment, author identity, or status-only signal. + +## Compatibility and migration + +A release contract binds one package/version and artifact inventory to one exact protected source generation. Evidence from an older head, merge result, or draft cannot transfer after source or expected assets change. A future release service or artifact layout requires explicit compatibility and migration rules for package consumers, provenance, draft-state recovery, and rollback while preserving historical immutable evidence rather than rewriting it. + ## Verification Use release-workflow regressions, expected-asset/digest tests, package and wheel consumers, reproducibility checks, security/coverage gates, SBOM/provenance/attestation checks where configured, formal review inspection, and post-publication artifact/checksum smoke verification. From ca47d58dff3f27eb00cf0b1435a21deed3c8d83f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:44:13 +0900 Subject: [PATCH 045/101] test(docs): require remaining minimum architecture decisions --- src/canonicalProductDocumentation.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index 092bf741..54c18f8d 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -32,6 +32,10 @@ const requiredFiles = [ 'docs/adr/0008-deterministic-office-rendering.md', 'docs/adr/0009-naruon-modular-composition.md', 'docs/adr/0010-release-evidence-authority.md', + 'docs/adr/0011-deterministic-vs-model-assisted-authoring.md', + 'docs/adr/0012-spreadsheet-formula-injection.md', + 'docs/adr/0013-atomic-file-publication.md', + 'docs/adr/0014-local-assets-font-licensing.md', ] as const; describe('canonical product documentation graph', () => { From 2aca72d17974ee2cf76840085a7c1661d5106530 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:44:54 +0900 Subject: [PATCH 046/101] docs(adr): separate deterministic and model-assisted authority --- ...terministic-vs-model-assisted-authoring.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/adr/0011-deterministic-vs-model-assisted-authoring.md diff --git a/docs/adr/0011-deterministic-vs-model-assisted-authoring.md b/docs/adr/0011-deterministic-vs-model-assisted-authoring.md new file mode 100644 index 00000000..34cfb1b4 --- /dev/null +++ b/docs/adr/0011-deterministic-vs-model-assisted-authoring.md @@ -0,0 +1,43 @@ +# ADR 0011: Deterministic conversion versus model-assisted authoring + +Status: Proposed + +## Context + +Inkspan supports deterministic editing/conversion surfaces and may be embedded in products that offer model-assisted writing. A generated proposal is probabilistic, provider-dependent content; deterministic document validation, conversion, revision, and persistence evidence must not inherit model authority or availability. + +## Alternatives considered + +- Let model output directly mutate or persist canonical documents. Rejected because provider behavior would become document authority and could bypass deterministic validation, host authorization, and user intent. +- Put model invocation inside deterministic conversion APIs. Rejected because conversion would gain network, credential, availability, privacy, and reproducibility dependencies. +- Keep model assistance as a host-authorized proposal path that rejoins Inkspan only through ordinary deterministic validation and explicit acceptance. Selected because it preserves offline-capable core behavior and a clear trust boundary. + +## Decision + +Deterministic editing, import/export, canonical envelope handling, revision evidence, autosave coordination, and Office rendering remain authoritative without an LLM or network dependency. Model-backed authoring is an optional host-owned capability. Model output is untrusted proposed content until an authorized host/user accepts it and the resulting content passes the same deterministic Inkspan parsing, sanitization, schema, conversion, and persistence boundaries as manually authored content. + +No model result authorizes a save, selects a tenant, advances a durable validator, bypasses clipboard or Office safety, changes a release gate, or becomes formal review evidence merely because the provider returned successfully. + +## Consequences + +Inkspan remains usable when model infrastructure is absent or degraded. Hosts can select providers and product UX independently. Model-assisted workflows incur an explicit proposal/diff/acceptance step and must maintain their own prompt/data governance and audit evidence. + +## Failure and recovery + +Provider timeout, quota exhaustion, malformed output, policy rejection, or unavailable credentials disables only the optional proposal path. Existing deterministic authoring and conversion remain available according to host policy. Invalid proposed content is rejected or sanitized through the normal deterministic boundary; it is never promoted to success by a fallback that skips validation. + +## Security and privacy impact + +The host owns model credentials, provider selection, external-data-use approval, prompt construction, redaction/minimization, retention, tenant authorization, and human approval. Inkspan must not rematerialize raw provider secrets after model execution or place prompts, model outputs, tenant data, or credentials into generic diagnostics. Model output is treated as attacker-controlled/untrusted content at every deterministic ingress. + +## Compatibility and migration + +Deterministic package APIs cannot acquire a required provider/network dependency in a compatible minor change. A future model-assistance SDK must remain optional and versioned separately from deterministic document/conversion contracts. Hosts may migrate model providers without changing canonical Inkspan document semantics. Rollback disables model assistance without document migration. + +## Verification + +Package-consumer tests prove deterministic subpaths work without model SDKs or credentials. Editor/conversion security tests exercise model-proposed content through the same sanitization/schema boundaries as other untrusted input. Host integration evidence must prove authorization and explicit acceptance before durable persistence. Outage tests verify deterministic authoring remains functional when the model path is unavailable. + +## Rollback or supersession + +Rollback removes or disables the optional proposal integration while preserving canonical documents and deterministic APIs. Supersession requires an explicit versioned trust-boundary ADR showing why any model-derived authority is necessary, with privacy, security, offline/degraded-mode, compatibility, migration, and rollback evidence. From fe5da8841ca52540a48e0e28654dcccd24ba5146 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:45:27 +0900 Subject: [PATCH 047/101] docs(adr): define spreadsheet formula safety authority --- .../adr/0012-spreadsheet-formula-injection.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/adr/0012-spreadsheet-formula-injection.md diff --git a/docs/adr/0012-spreadsheet-formula-injection.md b/docs/adr/0012-spreadsheet-formula-injection.md new file mode 100644 index 00000000..5f6769c5 --- /dev/null +++ b/docs/adr/0012-spreadsheet-formula-injection.md @@ -0,0 +1,43 @@ +# ADR 0012: Spreadsheet formula-injection handling + +Status: Proposed + +## Context + +Inkspan Office accepts AI-authored or otherwise untrusted JSON-like spreadsheet values and produces XLSX files. Spreadsheet applications can interpret text beginning with formula-significant prefixes such as `=`, `+`, `-`, or `@` as executable formulas or formula-like expressions if a renderer writes them with formula semantics. The 0.1 renderer contract does not include formula generation. + +## Alternatives considered + +- Preserve formula-looking strings as formulas. Rejected because untrusted text could gain executable spreadsheet semantics and formula generation is outside the current contract. +- Prefix every suspicious string with a visible apostrophe. Rejected as the primary contract because it mutates the user's textual value and can create avoidable fidelity differences. +- Write supported string values as literal text cells and verify that formula-significant prefixes remain data, while rejecting values that cannot be represented safely. Selected because it preserves user text without granting formula authority. + +## Decision + +String inputs are rendered as literal text by default, including values whose first non-whitespace character is `=`, `+`, `-`, or `@`. Inkspan Office does not infer or generate spreadsheet formulas in the current contract. Numeric and textual limits are validated before publication, and callers must supply identifiers or high-precision digit sequences as strings when exact textual representation matters. + +A future formula feature must use a distinct explicit schema field or versioned contract; it may not reinterpret existing string cells as formulas. + +## Consequences + +AI-authored and pasted content cannot silently become a formula merely because its text begins with a formula-significant prefix. Consumers that intentionally need formulas must wait for or adopt a future explicit formula contract rather than relying on implicit spreadsheet-library behavior. + +## Failure and recovery + +If a value cannot be represented under the safe literal/numeric contract, validation fails before successful artifact publication. The renderer must not fall back from rejected text to formula semantics. Recovery is to provide a supported literal representation or adopt a future explicit formula schema after its security review. + +## Security and privacy impact + +This boundary removes a common path from untrusted document content to spreadsheet formula execution, external-link behavior, or application-specific formula side effects. It does not make downstream spreadsheet viewers universally safe; hosts remain responsible for distribution policy, viewer hardening, authorization, and document classification. Formula-significant source strings are content and should not be copied into generic security logs solely because they were neutralized. + +## Compatibility and migration + +Existing string cells retain literal-text semantics across compatible releases. Introducing intentional formulas is a breaking semantic expansion unless represented by a new explicit versioned shape that coexists without changing old strings. Migration must distinguish literal historical values from intentional formulas and provide rollback to the literal-only renderer. + +## Verification + +Maintain regression fixtures for leading `=`, `+`, `-`, and `@`, including whitespace-prefixed variants and ordinary literal strings. Inspect generated XLSX cell types/values with the supported library and realistic package round-trips. Keep numeric-precision, string-length, worksheet-limit, package, coverage, and deterministic-render tests green on every supported Python runtime. + +## Rollback or supersession + +Rollback restores the last verified literal-only spreadsheet contract and rebuilds artifacts from exact source. Supersession requires an explicit formula schema, threat analysis, injection regressions, compatibility/migration rules, downstream-viewer considerations, and a safe rollback that never reinterprets historical literal strings. From 1a948393944b68de55674a5c20f8d54ea70c93a1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:45:52 +0900 Subject: [PATCH 048/101] docs(adr): define atomic file publication semantics --- docs/adr/0013-atomic-file-publication.md | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/adr/0013-atomic-file-publication.md diff --git a/docs/adr/0013-atomic-file-publication.md b/docs/adr/0013-atomic-file-publication.md new file mode 100644 index 00000000..11e58141 --- /dev/null +++ b/docs/adr/0013-atomic-file-publication.md @@ -0,0 +1,43 @@ +# ADR 0013: Atomic file publication and explicit overwrite semantics + +Status: Proposed + +## Context + +Deterministic Office rendering produces binary artifacts that may be published to caller-selected filesystem paths. A naïve check-then-write sequence can race another writer, expose partial files, or unexpectedly replace an existing artifact. Publication semantics therefore belong to the renderer's correctness and security contract, not only to operational convenience. + +## Alternatives considered + +- Write directly to the destination path. Rejected because consumers can observe partially written artifacts and a failed render can corrupt the target. +- Check whether the destination exists and then rename a temporary file into place. Rejected for non-overwrite mode because the check and publication are separate operations and can race another writer. +- Publish a complete same-directory temporary artifact through race-safe non-overwrite semantics, with a separate explicit overwrite mode using atomic replacement. Selected because partial output never becomes success and overwrite intent is unambiguous. + +## Decision + +Inkspan Office builds and validates the complete artifact before publication. Publication uses a securely created same-directory temporary file. The default non-overwrite path must atomically fail if the target already exists rather than replacing it after a check-then-act race. Replacement of an existing target is permitted only when the caller explicitly selects overwrite behavior, and that replacement must be atomic for the supported filesystem contract. + +Temporary/partial output is never returned as a successful `conversion_artifact`. Cleanup is bounded to the renderer's own temporary artifact and must not delete or rewrite unrelated caller files. + +## Consequences + +Callers get deterministic conflict behavior and never need to infer whether an existing artifact was replaced. Same-directory temporary publication has filesystem constraints and may cost an additional write/rename step, but it makes the success boundary reviewable and protects consumers from partial output. + +## Failure and recovery + +Validation, build, temporary-write, publication, destination-conflict, or replacement failure returns a bounded failure and leaves no successful-artifact claim. In default mode an existing destination is preserved. Recovery is to choose a new output path, remove/rename the target under caller authority, or explicitly request overwrite. Retrying must rebuild or reuse only a fully validated candidate under the documented contract. + +## Security and privacy impact + +Race-safe non-overwrite behavior reduces unintended clobbering and symlink/check-then-act style publication hazards within the supported path contract. Secure temporary files reduce exposure of predictable intermediate names. Inkspan does not broaden filesystem authority, traverse unrelated storage for cleanup, or infer that overwrite is safe from content identity. Hosts remain responsible for directory permissions, tenant path isolation, quotas, retention, encryption at rest, and downstream distribution. + +## Compatibility and migration + +Default non-overwrite behavior is a stable safety contract. Changing default replacement semantics would be breaking. Existing callers that intentionally replace files must continue to opt in explicitly. Any future object-store or remote-publication adapter requires a separate versioned compare/create/replace contract with equivalent conflict, partial-success, and rollback semantics rather than pretending filesystem atomicity applies remotely. + +## Verification + +Maintain tests for existing-target conflicts, explicit overwrite, simultaneous publication attempts, temporary-write/build failure, cleanup of only owned temporary artifacts, extension mismatch, and successful round-trip package integrity. Use concurrency regressions that prove the default path has no check-then-replace window and that a consumer never observes a partially published success artifact. + +## Rollback or supersession + +Rollback restores the last verified publication implementation without weakening default non-overwrite behavior. Supersession requires an explicit storage-specific atomicity model, conflict semantics, security review, concurrency tests, migration guidance, and a rollback that preserves already published caller artifacts. From 979e4ce8a1432ae66d9ce8a09775a2971266e42d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:46:27 +0900 Subject: [PATCH 049/101] docs(adr): define offline font asset and licensing boundary --- docs/adr/0014-local-assets-font-licensing.md | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 docs/adr/0014-local-assets-font-licensing.md diff --git a/docs/adr/0014-local-assets-font-licensing.md b/docs/adr/0014-local-assets-font-licensing.md new file mode 100644 index 00000000..a08c6047 --- /dev/null +++ b/docs/adr/0014-local-assets-font-licensing.md @@ -0,0 +1,45 @@ +# ADR 0014: Local assets and font-licensing boundary + +Status: Proposed + +## Context + +Inkspan is intended to remain usable in offline and air-gapped environments while rendering Korean, English, Japanese, Simplified Chinese, Traditional Chinese, Vietnamese, and other supported text predictably. Fetching web fonts at runtime would introduce availability, privacy, CSP/egress, and supply-chain dependencies. Bundling fonts also creates a redistribution/licensing obligation that must remain visible to package consumers and acquisition reviewers. + +The current package bundles Noto Sans-family WOFF2 subsets generated from the Google Fonts distribution. `src/fonts/OFL.txt` carries the SIL Open Font License 1.1 text and `src/fonts/NOTICE` records the bundled families, attribution, source, subset process, and license boundary. + +## Alternatives considered + +- Fetch fonts from Google Fonts or another CDN at runtime. Rejected because offline/air-gapped operation would fail and document rendering would gain external network, privacy, CSP, and provider-availability dependencies. +- Depend only on host/system fonts. Rejected as the default product contract because cross-platform glyph coverage, CJK/Vietnamese rendering, layout evidence, and acquisition reproducibility become host-specific. +- Bundle permissively redistributable local subsets with complete license/notice material and explicit package exports. Selected because rendering remains offline-capable while third-party asset obligations are reviewable. + +## Decision + +Inkspan bundles the supported Noto Sans-family font subsets as local package assets and exposes local CSS/font package paths. Runtime authoring/rendering must not require a remote font fetch. Bundled font software remains under SIL OFL-1.1; Inkspan application source remains under its own repository license. The OFL license text and attribution/NOTICE must ship with the redistributed font assets. + +The product does not rename, imply ownership of, or silently relicense the Noto font software. Any future modified font must respect Reserved Font Name and other OFL conditions before distribution. + +## Consequences + +Offline and closed-network consumers get stable multilingual font availability and do not leak document access through third-party font requests. Package size is larger, and font inventory/licensing becomes part of release verification. Host applications may still choose their own typography, but the documented Inkspan offline asset path remains available without network authority. + +## Failure and recovery + +If a required bundled asset, license text, attribution record, CSS mapping, or package export is missing or inconsistent, package/release verification fails rather than silently falling back to a remote URL. If a font license or provenance cannot be established, remove the affected asset from the release until a reviewed replacement or corrected provenance record exists. Runtime must not auto-download a substitute. + +## Security and privacy impact + +Local fonts eliminate runtime font-CDN requests that could disclose client IP, application access timing, origin/referrer information, or violate CSP/egress policy. Shipping only reviewed assets reduces remote supply-chain substitution risk. Font files remain untrusted binary assets for downstream browser/font parsers, so package provenance and bounded asset inventory matter even though Inkspan does not execute them as code. + +## Compatibility and migration + +Package paths such as the local font CSS/assets are consumer-facing compatibility surfaces. Removing a bundled family, changing unicode-range coverage, renaming a family, changing weights, or replacing licenses requires release notes and rendering/packaging compatibility evidence. Hosts can migrate to their own fonts without changing canonical document semantics because font choice is presentation, not document authority. Rollback restores the last verified local asset inventory and its matching license/NOTICE files. + +## Verification + +Package verification must confirm the expected font files, CSS exports, `src/fonts/OFL.txt`, and `src/fonts/NOTICE` are included as intended. Tests or release evidence should verify no canonical Inkspan stylesheet requires a remote font URL, multilingual fixtures render with the declared local families/weights, and asset/license inventory matches package metadata and documentation. Supply-chain review checks the recorded upstream provenance before changing bundled font bytes. + +## Rollback or supersession + +Rollback restores the previous verified font/CSS inventory together with its exact license and NOTICE material. Supersession requires an explicit asset/provenance/license decision with offline/degraded-mode behavior, package-size and rendering compatibility analysis, supply-chain review, migration guidance, and a no-network rollback path. From 7896c9abeb686ed0336e8f9a8f73f8248fef534e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:46:59 +0900 Subject: [PATCH 050/101] docs(adr): index complete minimum decision set --- docs/adr/README.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index 54f03c0d..3ff43390 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -16,6 +16,10 @@ This index records durable architectural decisions. Protected-main implementatio | [0008](0008-deterministic-office-rendering.md) | Proposed | Deterministic Office rendering boundary | | [0009](0009-naruon-modular-composition.md) | Proposed | Naruon modular composition without product coupling | | [0010](0010-release-evidence-authority.md) | Proposed | Release evidence authority | +| [0011](0011-deterministic-vs-model-assisted-authoring.md) | Proposed | Deterministic conversion versus model-assisted authoring | +| [0012](0012-spreadsheet-formula-injection.md) | Proposed | Spreadsheet formula-injection handling | +| [0013](0013-atomic-file-publication.md) | Proposed | Atomic file publication and explicit overwrite semantics | +| [0014](0014-local-assets-font-licensing.md) | Proposed | Local assets and font-licensing boundary | ## Decision discipline @@ -27,13 +31,16 @@ An ADR cannot promote an unmerged feature to shipped behavior. When a decision c ## ADR quality requirements -Every material ADR records: +Every material ADR records explicit sections for: 1. context and the problem boundary; -2. the selected decision and rejected authority expansion or alternative where material; -3. consequences and ownership trade-offs; -4. failure and recovery semantics; -5. verification/acceptance evidence; and -6. rollback or explicit supersession conditions. - -Security/privacy, compatibility, migration, accessibility, operability, and release implications belong in those sections when relevant. Canonical PRD, TRD, Architecture, UML, data/evidence model, threat model, test strategy, operability, and traceability documents must remain synchronized with Accepted decisions. +2. materially distinct alternatives considered; +3. the selected decision; +4. consequences and ownership trade-offs; +5. failure and recovery semantics; +6. security and privacy impact; +7. compatibility and migration behavior; +8. verification/acceptance evidence; and +9. rollback or explicit supersession conditions. + +Accessibility, operability, research/standards traceability, and release implications are included wherever the decision affects them. Canonical PRD, TRD, Architecture, contracts, UML, data/evidence model, threat model, test strategy, operability, and traceability documents must remain synchronized with Accepted decisions. From e26fd002ffaabcfaac0143207a5cd0b2e493c93f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:49:59 +0900 Subject: [PATCH 051/101] test(docs): bind offline font provenance and egress contract --- src/canonicalProductDocumentation.test.ts | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index 54c18f8d..b3ed4911 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -36,6 +36,10 @@ const requiredFiles = [ 'docs/adr/0012-spreadsheet-formula-injection.md', 'docs/adr/0013-atomic-file-publication.md', 'docs/adr/0014-local-assets-font-licensing.md', + 'src/fonts/OFL.txt', + 'src/fonts/NOTICE', + 'src/fonts/fonts.css', + 'src/fonts/fonts-latin.css', ] as const; describe('canonical product documentation graph', () => { @@ -149,6 +153,31 @@ describe('canonical product documentation graph', () => { expect(contracts).toContain('degraded'); }); + it('keeps offline font provenance and network-free asset contracts explicit', () => { + const license = repositoryFile('src/fonts/OFL.txt'); + const notice = repositoryFile('src/fonts/NOTICE'); + const fullFonts = repositoryFile('src/fonts/fonts.css'); + const latinFonts = repositoryFile('src/fonts/fonts-latin.css'); + + expect(license).toContain('SIL Open Font License, Version 1.1'); + expect(license).toContain('Reserved Font Name "Noto"'); + for (const marker of [ + 'Noto Sans', + 'Noto Sans KR', + 'Noto Sans JP', + 'Noto Sans SC', + 'Noto Sans TC', + 'air-gapped', + 'OFL-1.1', + ]) { + expect(notice).toContain(marker); + } + for (const stylesheet of [fullFonts, latinFonts]) { + expect(stylesheet).toContain("url('./files/"); + expect(stylesheet).not.toMatch(/https?:\/\//u); + } + }); + it('keeps detailed ADRs indexed and complete enough for acquisition review', () => { const index = repositoryFile('docs/adr/README.md'); From 598e3898ec62c3f58f4ea3ea299c71b02f86c574 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 20:51:43 +0900 Subject: [PATCH 052/101] docs: align changelog with canonical architecture graph --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3b67106..6c5949fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,8 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ## [Unreleased] ### Documentation -- Added a canonical acquisition documentation spine covering product requirements, technical requirements, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and ten linked architecture decision records without inventing Inkspan-owned persistence or host authority -- Added a machine-checkable canonical-documentation contract that keeps required files, ADR index links, browser-security evidence, standards references, rollback sections, and host-vs-Inkspan authority boundaries synchronized +- Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and fourteen linked architecture decision records without inventing Inkspan-owned persistence or host authority +- Added a machine-checkable canonical-documentation contract that keeps required files, ADR index links and completeness, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, and host-vs-Inkspan authority boundaries synchronized - Added an authoritative standalone and modular MSA architecture contract with reviewable deployment, optimistic-concurrency, data-ownership, security, and acquisition-evidence diagrams and tables - Added a beginner-readable naruon compose and ui.panel integration guide covering narrow client hydration, server-selected strong validators, accessible conflict handling, host-owned Yjs lifecycle, contextual-orchestrator boundaries, and local-versus-shareable evidence - Added an opaque editing-context remount for the complete editor and autosave example, latest-generation asynchronous capture ordering, encoded document path segments, redacted recovery status, and lazy state-owned session identity to prevent cross-document state reuse From 12f704623fe1f1217e209adfdd7d310e75a54610 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:08:56 +0900 Subject: [PATCH 053/101] test(docs): require product-definition status discipline --- src/canonicalProductDocumentation.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index b3ed4911..dbf7077e 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -78,6 +78,18 @@ describe('canonical product documentation graph', () => { } }); + it('does not promote active-PR product requirements to protected-main implementation', () => { + const prd = repositoryFile('docs/PRD.md'); + const productDefinition = prd.slice( + prd.indexOf('## Product definition'), + prd.indexOf('## Users and buyers'), + ); + + expect(productDefinition).toContain('Protected `main`'); + expect(productDefinition).toContain('Active PR / Proposed'); + expect(productDefinition).toContain('not shipped claims'); + }); + it('records host ownership and deterministic Inkspan authority consistently', () => { const prd = repositoryFile('docs/PRD.md'); const trd = repositoryFile('docs/TRD.md'); From 084e1f47ba094475813735110cbbccfd6699c3e7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:09:20 +0900 Subject: [PATCH 054/101] docs(prd): separate proposed requirements from shipped claims --- docs/PRD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PRD.md b/docs/PRD.md index 834c437e..990c9e70 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -4,7 +4,7 @@ Status: Proposed canonical baseline ## Product definition -Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. It gives hosts a TipTap/ProseMirror editor, safe rich clipboard handling, canonical document envelopes, revision-scoped evidence, SSR/native-form integration, bounded local autosave coordination, provider-neutral collaboration bindings, and deterministic Office conversion without taking ownership of host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, or model-use policy. +Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. This canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling, revision-scoped selection/transition evidence, SSR/native-form integration, and lifecycle observation; they are target requirements, not shipped claims, until protected integration. Across current and proposed scope, Inkspan keeps host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. The product promise is: **author, convert, collaborate, and prove document changes without hiding authority inside the editor.** From 85629eb919aea7c58a4760af2ab231726f9e6430 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:29:33 +0900 Subject: [PATCH 055/101] test(docs): require documentation fitness matrix --- src/canonicalProductDocumentation.test.ts | 40 ++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index dbf7077e..a18c3717 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -12,6 +12,7 @@ const requiredFiles = [ 'ARCHITECTURE.md', 'CHANGELOG.md', 'docs/README.md', + 'docs/DOCUMENTATION_FITNESS.md', 'docs/PRD.md', 'docs/TRD.md', 'docs/CONTRACTS.md', @@ -63,6 +64,7 @@ describe('canonical product documentation graph', () => { } for (const marker of [ '../ARCHITECTURE.md', + 'DOCUMENTATION_FITNESS.md', 'PRD.md', 'TRD.md', 'CONTRACTS.md', @@ -165,6 +167,42 @@ describe('canonical product documentation graph', () => { expect(contracts).toContain('degraded'); }); + it('keeps documentation completeness and implementation maturity explicit', () => { + const fitness = repositoryFile('docs/DOCUMENTATION_FITNESS.md'); + + for (const documentFamily of [ + 'PRD', + 'TRD', + 'ARCHITECTURE', + 'ADR', + 'UML', + 'DATA_MODEL / ERD', + 'SECURITY', + 'THREAT_MODEL', + 'TEST_STRATEGY', + 'OPERABILITY', + 'TRACEABILITY', + ]) { + expect(fitness).toContain(documentFamily); + } + + for (const status of [ + 'present_current', + 'owned_by_separate_active_pr', + 'implemented_on_protected_main', + 'implemented_on_active_pr', + 'planned', + 'not_applicable', + ]) { + expect(fitness).toContain(status); + } + + expect(fitness).toContain('physical relational ERD'); + expect(fitness).toContain('not_applicable'); + expect(fitness).toContain('Protected `main`'); + expect(fitness).toContain('not yet a protected-main canonical baseline'); + }); + it('keeps offline font provenance and network-free asset contracts explicit', () => { const license = repositoryFile('src/fonts/OFL.txt'); const notice = repositoryFile('src/fonts/NOTICE'); @@ -213,4 +251,4 @@ describe('canonical product documentation graph', () => { } } }); -}); +}); \ No newline at end of file From ab331896a0a821eb24f70a921889d0dcd8cd951f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:30:18 +0900 Subject: [PATCH 056/101] docs: record canonical documentation fitness --- docs/DOCUMENTATION_FITNESS.md | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/DOCUMENTATION_FITNESS.md diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md new file mode 100644 index 00000000..1e1a3384 --- /dev/null +++ b/docs/DOCUMENTATION_FITNESS.md @@ -0,0 +1,85 @@ +# Inkspan Documentation Fitness Matrix + +Status: Proposed canonical baseline + +This document answers a narrower acquisition question than the PRD or architecture: **can an independent reviewer reconstruct Inkspan's product, technical, security, data/evidence, operating, and release decisions from GitHub without relying on chat history or pull-request prose?** + +Protected `main` remains the implementation authority. This documentation branch is reviewable evidence, but it is **not yet a protected-main canonical baseline** until normal protected integration succeeds. Requirements implemented only on another active branch are not shipped merely because this matrix references them. + +## Classification vocabulary + +Documentation-family fitness uses exactly these values: + +- `present_current` — the canonical document exists on the source generation being reviewed and matches the reviewed product boundary. +- `present_stale` — a document exists but conflicts with current implementation or accepted decisions. +- `partial` — useful authoritative material exists, but one or more required decisions or views are not yet covered. +- `missing` — no adequate canonical artifact exists. +- `not_applicable` — omission is deliberate and the reason is explicit. +- `owned_by_separate_active_pr` — another non-overlapping active branch owns the canonical artifact; this branch must reference rather than duplicate it. + +Implementation maturity uses exactly these values: + +- `implemented_on_protected_main` +- `implemented_on_active_pr` +- `partial` +- `accepted_architecture` +- `planned` +- `research_only` +- `superseded` +- `out_of_scope` + +Document fitness and implementation maturity are independent. A `present_current` PRD may describe both `implemented_on_protected_main` and `planned` requirements so long as those states are explicit. + +## Canonical documentation fitness + +| Family | Canonical artifact | Documentation fitness | Implementation / authority interpretation | Acquisition conclusion | +| --- | --- | --- | --- | --- | +| PRD | `docs/PRD.md` | `present_current` | Mix of `implemented_on_protected_main`, `implemented_on_active_pr`, and `planned`, explicitly labeled | Product promise, users, JTBD, non-goals, security, accessibility and release acceptance are reconstructable. | +| TRD | `docs/TRD.md` | `present_current` | Same mixed maturity discipline; Protected `main` remains runtime authority | Technical invariants, failure semantics, package boundaries and release evidence are reconstructable. | +| ARCHITECTURE | `ARCHITECTURE.md` | `present_current` | `implemented_on_protected_main` for the bounded standalone/modular architecture | Host-vs-Inkspan authority and modular CWL composition are explicit. | +| Public/API/schema/plugin contracts | `docs/CONTRACTS.md` | `present_current` | Protected-main contracts plus explicitly proposed extensions | Integration authority and degraded behavior are not hidden in implementation details. | +| ADR | `docs/adr/README.md` and detailed ADRs | `present_current` | Decisions distinguish current, proposed and future work | Alternatives, consequences, recovery, migration, verification and supersession are reviewable. | +| UML | `docs/UML.md` | `present_current` | Diagrams include protected-main and clearly proposed flows | Component, sequence, state, deployment, degraded-mode and authority flows are visible as diagram-as-code. | +| DATA_MODEL / ERD | `docs/DATA_MODEL.md` | `present_current` | Current logical evidence/domain model; host persistence remains outside Inkspan | The model distinguishes document/evidence/conversion/release values from host-owned entities. | +| physical relational ERD | none by design | `not_applicable` | `out_of_scope` while Inkspan owns no application database | No fake database is invented merely to satisfy an ERD checklist; a physical ERD becomes mandatory if persistence authority moves into Inkspan. | +| SECURITY disclosure policy | root `SECURITY.md` | `owned_by_separate_active_pr` | `implemented_on_active_pr` until protected integration | This branch must not race the separately owned disclosure-policy line. | +| THREAT_MODEL | `docs/THREAT_MODEL.md` | `present_current` | Covers current and explicitly proposed trust boundaries | Clipboard, Office, SSR/form, Yjs, model, host-authority and supply-chain threats are reconstructable. | +| TEST_STRATEGY | `docs/TEST_STRATEGY.md` | `present_current` | Current deterministic evidence plus `planned` cross-engine acceptance where dependency order requires it | Test authority and claim limits are explicit rather than inferred from CI badges. | +| OPERABILITY | `docs/OPERABILITY.md` | `present_current` | Current local/product responsibilities plus host-owned recovery boundaries | Conflict, collaboration, conversion and release recovery/rollback ownership are explicit. | +| Release / rollback / provenance | TRD, OPERABILITY and release ADRs | `present_current` | Mix of `implemented_on_protected_main` and active hardening | Exact-source release authority, stale-evidence rejection and rollback are reconstructable. | +| Migration/version routing | envelope contracts, TRD, DATA_MODEL and tracked migration-routing work | `partial` | Current parser is strict; bounded identity-only migration routing is `planned` | Host migration ownership is clear, but the public migration-routing aid remains a product gap until implemented and integrated. | +| TRACEABILITY | `docs/TRACEABILITY.md` | `present_current` | Links standards/research/requirements to decisions and evidence with scoped claims | Acquisition reviewers can distinguish evidence from aspiration. | +| Contributor/agent authority | `AGENTS.md`, `CLAUDE.md`, `docs/README.md` | `present_current` | Protected-main-first decision discipline | Agents are directed back to the same canonical graph rather than parallel private memory. | + +## Conversation-to-GitHub reconciliation + +The canonical graph must retain durable product decisions from the project conversation only when they agree with live implementation or are explicitly labeled as target architecture. The reviewed baseline currently covers: + +- Markdown/HTML WYSIWYG authoring and deterministic source/document authority; +- strict link, image, clipboard, envelope and revision/evidence boundaries; +- bundled local/offline font licensing and air-gapped asset behavior; +- deterministic email/document conversion boundaries and independently reusable Office rendering; +- provider-neutral collaboration with host-owned Yjs provider, room, persistence and awareness authority; +- naruon `compose` / `ui.panel` modular integration without making naruon a standalone runtime dependency; +- model assistance as untrusted proposed content rather than conversion or persistence authority; +- accessibility, keyboard, print/export and document-fidelity evidence boundaries; +- host ownership of transport, identity, authorization, tenancy, persistence, credentials, migration, retention, deployment, durable audit and model policy; and +- exact-head/package/security/provenance/release evidence as separate authorities from comments, model verdicts and historical checks. + +Where an older conversation, PR body, or plan conflicts with Protected `main`, it is historical rather than canonical. Where a requirement is only on an active PR, this documentation may describe it as `implemented_on_active_pr` but never as shipped. + +## Remaining documentation and product gaps + +The documentation pack itself is substantially complete for acquisition review, but **repository closure is not documentation closure**. The remaining gaps are intentionally represented rather than hidden: + +1. The security disclosure policy remains `owned_by_separate_active_pr`; after protected merge, this graph must be reconciled against the actual root `SECURITY.md`. +2. Migration/version routing remains `partial` because the safe identity-only routing API is still `planned`; its implementation requires the existing strict envelope parser to remain current-schema-only. +3. Cross-engine rich-clipboard assurance is `planned` behind the safe-clipboard integration dependency; browser-semantic claims must not be promoted from jsdom-only evidence. +4. Active feature branches for autosave observation, revision evidence, SSR/native forms, accessibility, release hardening and runtime compatibility remain `implemented_on_active_pr` until protected integration. +5. Documentation becoming mergeable or protected-merged is not a reason for the commercial loop to stop; the next safe product, release, security, accessibility or interoperability lane must continue. + +## Sufficiency decision + +For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability and traceability are `present_current`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. The repository security disclosure policy is separately owned and therefore `owned_by_separate_active_pr` rather than duplicated. + +Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph and the separately owned security policy pass their exact-head checks/reviews and normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. From d7098d0bf0b1886281750696ffedba52fcc10b2c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:30:34 +0900 Subject: [PATCH 057/101] docs: index documentation fitness matrix --- docs/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/README.md b/docs/README.md index f2181015..85ee5a56 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ This directory is the discoverable index for Inkspan's product, technical, secur | Document | Authority | | --- | --- | | [`../ARCHITECTURE.md`](../ARCHITECTURE.md) | Current protected-main implementation architecture and bounded-context ownership | +| [`DOCUMENTATION_FITNESS.md`](DOCUMENTATION_FITNESS.md) | Acquisition completeness matrix, implementation maturity, deliberate non-applicability and remaining canonical gaps | | [`PRD.md`](PRD.md) | Product users, jobs, buyer outcomes, non-goals, acceptance and claim boundaries | | [`TRD.md`](TRD.md) | Technical invariants, runtime boundaries, failure semantics and release evidence | | [`CONTRACTS.md`](CONTRACTS.md) | Public package/API/event/schema/plugin/collaboration and host-integration contracts | @@ -34,6 +35,8 @@ Use these terms consistently: - **Superseded** — retained only for history; a newer decision or implementation is authoritative. - **Out of scope** — deliberately excluded from Inkspan ownership. +The exact machine-oriented documentation-fitness and implementation-maturity vocabulary is defined in [`DOCUMENTATION_FITNESS.md`](DOCUMENTATION_FITNESS.md). Human-facing labels above must map to those states without combining evidence qualifiers, PR numbers, or temporary execution status into the status value itself. + Never use a PR body, check status, model verdict, local test, or conversation as a substitute for protected-main implementation authority. ## Ownership boundary From 4cacb3c67cbe504c120665a37525469585c32a6e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:42:03 +0900 Subject: [PATCH 058/101] test(docs): require migration and browser assurance decisions --- ...nicalDocumentationDecisionCoverage.test.ts | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/canonicalDocumentationDecisionCoverage.test.ts diff --git a/src/canonicalDocumentationDecisionCoverage.test.ts b/src/canonicalDocumentationDecisionCoverage.test.ts new file mode 100644 index 00000000..b9494d70 --- /dev/null +++ b/src/canonicalDocumentationDecisionCoverage.test.ts @@ -0,0 +1,70 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import { describe, expect, it } from 'vitest'; + +/** Read one authoritative repository document as UTF-8 text. */ +function repositoryFile(path: string): string { + return readFileSync(resolve(process.cwd(), path), 'utf8'); +} + +const migrationAdr = + 'docs/adr/0015-envelope-schema-migration-routing.md'; +const browserAssuranceAdr = + 'docs/adr/0016-cross-engine-browser-assurance.md'; + +describe('canonical architecture decision coverage', () => { + it('requires durable ADRs for migration routing and browser-semantic release assurance', () => { + for (const path of [migrationAdr, browserAssuranceAdr]) { + expect(existsSync(resolve(process.cwd(), path)), path).toBe(true); + } + + const index = repositoryFile('docs/adr/README.md'); + expect(index).toContain('0015-envelope-schema-migration-routing.md'); + expect(index).toContain('0016-cross-engine-browser-assurance.md'); + expect(index).toContain('Envelope schema identity and host-owned migration routing'); + expect(index).toContain('Cross-engine browser-semantic release assurance'); + }); + + it('keeps the new decisions complete enough for acquisition review', () => { + for (const path of [migrationAdr, browserAssuranceAdr]) { + const adr = repositoryFile(path); + expect(adr).toContain('Status: Proposed'); + for (const heading of [ + '## Context', + '## Alternatives considered', + '## Decision', + '## Consequences', + '## Failure and recovery', + '## Security and privacy impact', + '## Compatibility and migration', + '## Verification', + '## Rollback or supersession', + '## References', + ]) { + expect(adr).toContain(heading); + } + } + }); + + it('distinguishes documentation completeness from planned implementation maturity', () => { + const fitness = repositoryFile('docs/DOCUMENTATION_FITNESS.md'); + expect(fitness).toContain('Envelope schema identity / migration routing'); + expect(fitness).toContain('Cross-engine browser-semantic release assurance'); + expect(fitness).toContain('present_current'); + expect(fitness).toContain('planned'); + expect(fitness).toContain('Issue #74'); + expect(fitness).toContain('Issue #66'); + }); + + it('makes both decision paths reviewable as diagrams and standards traceability', () => { + const uml = repositoryFile('docs/UML.md'); + const traceability = repositoryFile('docs/TRACEABILITY.md'); + + expect(uml).toContain('## Envelope identity and host-owned migration routing'); + expect(uml).toContain('## Cross-engine browser-semantic release assurance'); + expect(traceability).toContain('Envelope version routing'); + expect(traceability).toContain('Cross-engine release assurance'); + expect(traceability).toContain('RFC 7493'); + }); +}); From 09c8c5bd9ce68dfaa30f243a2063629cbf2d8861 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:42:40 +0900 Subject: [PATCH 059/101] docs(adr): define envelope migration routing authority --- .../0015-envelope-schema-migration-routing.md | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs/adr/0015-envelope-schema-migration-routing.md diff --git a/docs/adr/0015-envelope-schema-migration-routing.md b/docs/adr/0015-envelope-schema-migration-routing.md new file mode 100644 index 00000000..5995c1e4 --- /dev/null +++ b/docs/adr/0015-envelope-schema-migration-routing.md @@ -0,0 +1,68 @@ +# ADR 0015: Envelope schema identity and host-owned migration routing + +Status: Proposed + +## Context + +Inkspan's protected implementation uses a strict versioned document envelope so canonical document bytes, revisions, restore behavior, and conversion contracts are not silently reinterpreted. The current parser is intentionally current-schema-only. That protects document semantics, but it also means a host that receives a structurally valid legacy or future envelope cannot use the strict parser merely to learn which migration route should handle it. + +Issue #74 tracks a bounded identity-only inspection surface for that gap. The architectural question is whether Inkspan should become a migration engine, relax the current parser, require every host to reimplement hostile-input parsing, or expose only enough validated schema identity to let the host select its own migration. + +## Alternatives considered + +- Make the current envelope parser permissive for unknown versions. Rejected because identifying a version is not the same as validating that version's document semantics; permissive parsing would weaken the source/revision authority in ADR 0002. +- Require each host to parse untrusted envelope JSON independently before calling Inkspan. Rejected because duplicate-name, strict UTF-8, resource-limit, accessor, descriptor, and redacted-error boundaries would drift across hosts exactly where version routing must be trustworthy. +- Move schema registry, migration execution, persistence transactions, rollback, and audit into Inkspan. Rejected because durable migration is host-owned under ADR 0001 and would couple the standalone editor to application persistence and tenancy. +- Provide a bounded identity-only inspection API while retaining strict current-schema parsing. Selected because it reuses Inkspan's deterministic hostile-input boundary without granting migration or persistence authority. + +## Decision + +Inkspan may expose a framework-independent identity inspector that returns only a frozen `schemaId` and positive safe-integer `schemaVersion` after bounded structural validation. The inspector is a dispatcher aid, not a document parser or migration engine. + +The identity path must share the envelope's existing byte, string, depth, value-count, JSON, duplicate-name, strict UTF-8, BOM, plain-object, descriptor, accessor, proxy/reflection, and redacted-error boundaries where applicable. It may require the complete envelope and the presence of `documentJson` while deliberately avoiding current TipTap/ProseMirror semantic validation of that member before returning routing metadata. It may ignore future fields only when doing so requires no accessor execution and does not weaken complete-input validation. + +`parseDocumentEnvelope()` remains strict and current-schema-only. After identity inspection, the host selects and executes any migration, authorizes the operation, chooses schema-registry policy, performs durable persistence, records audit evidence, applies tenant isolation and retention, and decides rollback. A migrated result must re-enter the ordinary strict current-schema validation path before it can become canonical Inkspan document state. + +## Consequences + +A host can route old or future envelopes without duplicating a second untrusted JSON parser, while Inkspan avoids accepting unknown document semantics. The public API gains one additional versioned evidence/value surface, so package consumers and acquisition reviewers can distinguish schema identification from migration success. + +The identity result is intentionally too small to support editing, authorization, durable persistence, or provenance claims. A host that needs richer legacy metadata must obtain it from the version-specific migration component rather than widening this generic inspector. + +## Failure and recovery + +Malformed JSON or UTF-8, duplicate names, missing identity/body members, invalid scalar types, unsafe version numbers, accessors, hostile proxies, decorated roots, resource-limit violations, or reflection failures fail closed with stable redacted errors. No partial identity is returned. + +An unsupported identity is not itself an error if the bounded identity contract is valid; it is a routing result. If no host migration is registered, the host keeps the original source unchanged and reports an unsupported-version outcome. Migration failure does not alter the original envelope and does not permit the current parser to accept the unsupported representation. + +## Security and privacy impact + +The inspector performs no network, file-system, environment, credential, database, scheduler, model, or collaboration-provider operation. It does not return `documentJson`, document text, links, inline image data, source-controlled property names, tenant identifiers, actor data, credentials, transport state, signatures, or durable-write claims. + +Schema identity can still be application metadata, so hosts may classify it as tenant-confidential. Public errors and generic telemetry must not echo arbitrary schema strings or private exception causes. The inspector does not authorize migration and does not prove that a supplied envelope came from a trusted actor. + +## Compatibility and migration + +Existing current-schema create/parse/encode/revision/restore behavior remains unchanged. The identity inspector is additive and must be available from a framework-independent package surface without pulling in React, TipTap UI, ProseMirror view, Yjs, DOM globals, network clients, or model SDKs. + +Any future change to envelope identity fields, canonicalization, or digest meaning requires an explicit new versioned contract and corresponding ADR update or supersession. Migration implementations remain host-owned and version-specific; this ADR does not define a universal transformation between arbitrary schema generations. + +## Verification + +Issue #74 defines the test-first implementation acceptance. Verification must include legacy/current/future identity, JSON text and strict UTF-8 bytes, duplicate names, malformed input, hostile JavaScript descriptors/proxies, resource limits, recursive absence of document-bearing output, deterministic repeated inspection, packed ESM/CommonJS/strict-TypeScript consumers, and proof that the strict current parser still rejects unsupported schemas. + +Repository-wide exact owned production statement/branch/function/line coverage and public docstring gates remain unchanged. Exact-head CI, security, package, provenance, review, and branch-protection evidence are required before the implementation can become protected-main authority. + +## Rollback or supersession + +Before protected integration, rollback removes the proposed inspector and leaves the strict parser plus host-owned migration guidance unchanged. After integration, removal or semantic broadening is a compatibility change requiring package-version review and migration guidance. + +Supersession is acceptable only if a later design preserves or strengthens the separation between bounded schema identification, strict current-schema validation, and host-owned migration/persistence authority. + +## References + +Bray, T. (Ed.). (2015). *The I-JSON Message Format* (RFC 7493). RFC Editor. https://doi.org/10.17487/RFC7493 + +Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) Data Interchange Format* (RFC 8259; STD 90). RFC Editor. https://doi.org/10.17487/RFC8259 + +Rundgren, A., Jordan, B., & Erdtman, S. (2020). *JSON Canonicalization Scheme (JCS)* (RFC 8785). RFC Editor. https://doi.org/10.17487/RFC8785 From 8393842e37360de23b82b2c8155dcf841275f9f2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:43:16 +0900 Subject: [PATCH 060/101] docs(adr): define cross-engine clipboard release assurance --- .../0016-cross-engine-browser-assurance.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/adr/0016-cross-engine-browser-assurance.md diff --git a/docs/adr/0016-cross-engine-browser-assurance.md b/docs/adr/0016-cross-engine-browser-assurance.md new file mode 100644 index 00000000..aaac3cfa --- /dev/null +++ b/docs/adr/0016-cross-engine-browser-assurance.md @@ -0,0 +1,72 @@ +# ADR 0016: Cross-engine browser-semantic release assurance + +Status: Proposed + +## Context + +Inkspan's safe rich-clipboard boundary depends on browser HTML fragment parsing, DOM construction, serialization, hidden-content interpretation, and TipTap/ProseMirror integration. Unit and jsdom evidence is valuable but cannot prove that Chromium, Firefox, and WebKit expose identical security-relevant behavior. Earlier development already found a CSSOM mismatch around proprietary Office style handling, demonstrating that one simulated DOM is not a sufficient publication boundary. + +PR #65 owns the sanitizer implementation. Issue #66 separately owns the browser-realistic differential release gate after PR #65 reaches protected `main`. The architectural decision is how browser-semantic differences are admitted into a release without turning engine disagreement into either an unbounded compatibility promise or an excuse to normalize away a security defect. + +## Alternatives considered + +- Treat jsdom/unit success as browser conformance. Rejected because simulated DOM behavior is not authoritative for real engine fragment parsing or serialization. +- Test only Chromium. Rejected because Inkspan is a browser-facing package and security semantics can diverge in Firefox or WebKit even when Chromium is green. +- Require byte-identical output from all engines without exception. Rejected because standards-permitted serialization differences can exist and unconditional normalization can hide a real semantic discrepancy. +- Run one dependency-locked adversarial corpus across Chromium, Firefox, and WebKit, require semantic parity for security decisions, and admit only narrowly reviewed standards-grounded differences. Selected because it provides buyer-reviewable evidence without claiming universal engine identity. + +## Decision + +Before a release line can claim the rich-clipboard boundary as supported, the same committed adversarial corpus must execute through Inkspan's public sanitizer and supported paste integration in named Playwright `chromium`, `firefox`, and `webkit` projects on one exact source head. + +The suite is hermetic and network-free, depends on immutable package/workflow pins, and does not require operating-system clipboard permissions. It covers strict element/attribute allowlisting; unsafe-link handling; scripts, resources, embeds, forms, metadata, media, SVG/MathML and images; interactive/obsolete fallback structures; hidden and Office-specific content; malformed fragment/table/list/formatting/namespace cases; hostile DOM capabilities; bounded bytes/nodes/depth; stable redacted failures; and representative performance alarms. + +Security-relevant semantic decisions must agree across required engines. A serialization difference may be allowlisted only when a focused fixture, authoritative standards basis, threat analysis, exact affected engine/version evidence, expected canonical interpretation, and rollback note show that the difference does not weaken the trust boundary. An allowlist is code-reviewed evidence, not a generic normalizer. + +The gate fails closed when a required browser is absent, skipped, cancelled, unsuccessful, or cannot produce the required evidence. Queued or pending execution is not success. Exact-head evidence records the package lock, Playwright version, browser revisions, operating system, corpus version, and source SHA without exposing private clipboard data or local paths. + +## Consequences + +Rich clipboard publication costs more CI time and browser artifacts, but acquisition reviewers receive direct evidence for the parser/serializer boundary most likely to vary by browser. Engine upgrades become observable compatibility events rather than silent semantic changes. + +The gate does not make Inkspan responsible for branded browser enterprise policy, extensions, host CSP, downstream rendering, transport, authorization, tenancy, persistence, credentials, retention, migration, or model policy. Those remain separate host/runtime controls. + +## Failure and recovery + +A newly divergent fixture blocks the release lane. The first response is to classify whether the divergence changes the security/semantic result, is a standards-permitted serialization-only difference, or exposes a test/environment defect. Repair the sanitizer or integration test-first when the boundary is unsafe. Add a focused reviewed allowance only for a proven safe difference. + +Do not delete a failing engine, weaken the corpus, convert a required project to optional, hide the failure behind retries, or reuse predecessor-head browser evidence. If browser provisioning itself is unavailable, the release remains blocked while unrelated Inkspan work continues. + +## Security and privacy impact + +The differential corpus contains committed synthetic fixtures only. Browser jobs receive no tenant document, production clipboard payload, provider credential, model credential, or persistence secret. Network access is disabled for the test scenario where practical, and logs/artifacts must not emit raw hostile input outside the public fixture set. + +The design reduces parser-confusion, hidden-content, active-resource, serialization, and regression risk. It does not replace host CSP, egress policy, authorization, tenant isolation, or application security testing. + +## Compatibility and migration + +Each accepted browser/Playwright revision is part of release evidence rather than a forever-supported browser guarantee. Upgrading Playwright or its browser revisions requires the complete corpus to rerun before the new evidence becomes authoritative. A future browser difference that is safe only behind a narrower supported construct must be reflected in the public compatibility contract rather than silently normalized. + +The gate is ordered behind the safe-clipboard implementation because there is no useful release assurance for a trust boundary that is not yet integrated. It does not change existing document-envelope or persistence migration semantics. + +## Verification + +Issue #66 defines the test-first implementation acceptance. Required proof includes RED evidence that the differential harness detects an intentionally introduced divergence or unsafe reconstruction, GREEN evidence after removing the fault, all three named browser projects, deterministic corpus/allowlist/evidence-generation tests, representative performance bounds, exact-head CI/security/package evidence, and a qualifying independent review before the release gate is accepted. + +The canonical documentation and test strategy must continue to state that jsdom-only evidence is not real-engine conformance and that differences are never normalized merely to make engines agree. + +## Rollback or supersession + +Before protected integration, rollback removes the proposed browser gate while leaving the rich-clipboard release line explicitly unaccepted for publication. After integration, disabling a required engine or loosening difference admission is a security/release-policy change requiring a superseding ADR and new threat analysis. + +Supersession is acceptable only if a later harness provides equivalent or stronger real-engine coverage and preserves exact-head, fail-closed, synthetic-fixture, and reviewed-difference boundaries. + +## References + +Microsoft. (n.d.-a). *Browsers*. Playwright documentation. Retrieved August 9, 2026, from https://playwright.dev/docs/browsers + +Microsoft. (n.d.-b). *Projects*. Playwright documentation. Retrieved August 9, 2026, from https://playwright.dev/docs/test-projects + +Web Hypertext Application Technology Working Group. (2026). *HTML Standard: Parsing HTML documents* (Living Standard). Retrieved August 9, 2026, from https://html.spec.whatwg.org/multipage/parsing.html + +World Wide Web Consortium. (2026, June 24). *Clipboard API and events* (W3C Working Draft). https://www.w3.org/TR/2026/WD-clipboard-apis-20260624/ From 2edf83835c54ee2c40db11e832edeb032344882d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:43:36 +0900 Subject: [PATCH 061/101] docs(adr): index migration and browser assurance decisions --- docs/adr/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/adr/README.md b/docs/adr/README.md index 3ff43390..88a5c403 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -20,6 +20,8 @@ This index records durable architectural decisions. Protected-main implementatio | [0012](0012-spreadsheet-formula-injection.md) | Proposed | Spreadsheet formula-injection handling | | [0013](0013-atomic-file-publication.md) | Proposed | Atomic file publication and explicit overwrite semantics | | [0014](0014-local-assets-font-licensing.md) | Proposed | Local assets and font-licensing boundary | +| [0015](0015-envelope-schema-migration-routing.md) | Proposed | Envelope schema identity and host-owned migration routing | +| [0016](0016-cross-engine-browser-assurance.md) | Proposed | Cross-engine browser-semantic release assurance | ## Decision discipline From c75f51aa1bede7cac87badc2e093fedf970fe578 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:44:31 +0900 Subject: [PATCH 062/101] docs: reconcile migration and browser assurance fitness --- docs/DOCUMENTATION_FITNESS.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 1e1a3384..80637249 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -47,7 +47,8 @@ Document fitness and implementation maturity are independent. A `present_current | TEST_STRATEGY | `docs/TEST_STRATEGY.md` | `present_current` | Current deterministic evidence plus `planned` cross-engine acceptance where dependency order requires it | Test authority and claim limits are explicit rather than inferred from CI badges. | | OPERABILITY | `docs/OPERABILITY.md` | `present_current` | Current local/product responsibilities plus host-owned recovery boundaries | Conflict, collaboration, conversion and release recovery/rollback ownership are explicit. | | Release / rollback / provenance | TRD, OPERABILITY and release ADRs | `present_current` | Mix of `implemented_on_protected_main` and active hardening | Exact-source release authority, stale-evidence rejection and rollback are reconstructable. | -| Migration/version routing | envelope contracts, TRD, DATA_MODEL and tracked migration-routing work | `partial` | Current parser is strict; bounded identity-only migration routing is `planned` | Host migration ownership is clear, but the public migration-routing aid remains a product gap until implemented and integrated. | +| Envelope schema identity / migration routing | ADR 0015, PRD, TRD, DATA_MODEL and Issue #74 | `present_current` | Identity-only routing capability is `planned`; strict current-schema parsing and host migration ownership remain authoritative | The architecture now distinguishes bounded schema identification from host-owned migration execution without calling the planned API shipped. | +| Cross-engine browser-semantic release assurance | ADR 0016, UML, TEST_STRATEGY, TRACEABILITY and Issue #66 | `present_current` | Differential Chromium/Firefox/WebKit release gate is `planned` behind PR #65 | Browser-realistic security assurance is a durable release decision even though its implementation remains dependency-ordered future work. | | TRACEABILITY | `docs/TRACEABILITY.md` | `present_current` | Links standards/research/requirements to decisions and evidence with scoped claims | Acquisition reviewers can distinguish evidence from aspiration. | | Contributor/agent authority | `AGENTS.md`, `CLAUDE.md`, `docs/README.md` | `present_current` | Protected-main-first decision discipline | Agents are directed back to the same canonical graph rather than parallel private memory. | @@ -63,9 +64,13 @@ The canonical graph must retain durable product decisions from the project conve - naruon `compose` / `ui.panel` modular integration without making naruon a standalone runtime dependency; - model assistance as untrusted proposed content rather than conversion or persistence authority; - accessibility, keyboard, print/export and document-fidelity evidence boundaries; -- host ownership of transport, identity, authorization, tenancy, persistence, credentials, migration, retention, deployment, durable audit and model policy; and +- host ownership of transport, identity, authorization, tenancy, persistence, credentials, migration, retention, deployment, durable audit and model policy; +- strict current-schema parsing plus planned identity-only envelope routing, while migration execution remains host-owned; +- real Chromium/Firefox/WebKit differential evidence as a release gate for browser-semantic clipboard security rather than a jsdom conformance claim; and - exact-head/package/security/provenance/release evidence as separate authorities from comments, model verdicts and historical checks. +Autonomous commercial-maintenance scheduling and the no-early-stop execution discipline are **control-plane governance, not a shipped Inkspan product capability**. The scheduler prompt is the execution authority for that loop; repository guidance records writer leases, evidence hierarchy and protected-main authority without pretending the automation prompt is a runtime API or architectural feature. + Where an older conversation, PR body, or plan conflicts with Protected `main`, it is historical rather than canonical. Where a requirement is only on an active PR, this documentation may describe it as `implemented_on_active_pr` but never as shipped. ## Remaining documentation and product gaps @@ -73,13 +78,13 @@ Where an older conversation, PR body, or plan conflicts with Protected `main`, i The documentation pack itself is substantially complete for acquisition review, but **repository closure is not documentation closure**. The remaining gaps are intentionally represented rather than hidden: 1. The security disclosure policy remains `owned_by_separate_active_pr`; after protected merge, this graph must be reconciled against the actual root `SECURITY.md`. -2. Migration/version routing remains `partial` because the safe identity-only routing API is still `planned`; its implementation requires the existing strict envelope parser to remain current-schema-only. -3. Cross-engine rich-clipboard assurance is `planned` behind the safe-clipboard integration dependency; browser-semantic claims must not be promoted from jsdom-only evidence. +2. Issue #74 remains `planned`: the identity-only migration-routing API must still be implemented test-first while the current parser remains strict. Its architectural decision is now present rather than hidden in issue prose. +3. Issue #66 remains `planned` behind PR #65: the dependency-locked Chromium/Firefox/WebKit differential suite must still be implemented before the rich-clipboard release line. Its release-assurance decision is now present rather than hidden in issue prose. 4. Active feature branches for autosave observation, revision evidence, SSR/native forms, accessibility, release hardening and runtime compatibility remain `implemented_on_active_pr` until protected integration. 5. Documentation becoming mergeable or protected-merged is not a reason for the commercial loop to stop; the next safe product, release, security, accessibility or interoperability lane must continue. ## Sufficiency decision -For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability and traceability are `present_current`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. The repository security disclosure policy is separately owned and therefore `owned_by_separate_active_pr` rather than duplicated. +For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Envelope migration routing and cross-engine browser assurance are now explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. The repository security disclosure policy is separately owned and therefore `owned_by_separate_active_pr` rather than duplicated. -Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph and the separately owned security policy pass their exact-head checks/reviews and normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. +No material product architecture decision identified by this review remains only in chat or issue prose. Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph and the separately owned security policy pass their exact-head checks/reviews and normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. From 071015268469bfd45bd3ec2c8a07189249830fa5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:45:11 +0900 Subject: [PATCH 063/101] docs(uml): diagram migration routing and browser assurance --- docs/UML.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/docs/UML.md b/docs/UML.md index 9b7ece0e..be12bc84 100644 --- a/docs/UML.md +++ b/docs/UML.md @@ -59,6 +59,42 @@ sequenceDiagram Security-relevant browser fragment semantics require the same hostile corpus under Chromium, Firefox, and WebKit before the relevant release line. +## Cross-engine browser-semantic release assurance + +```mermaid +flowchart TB + Head[One exact protected-source candidate head] + Corpus[Committed synthetic adversarial clipboard corpus] + Lock[Immutable package lock and Playwright/browser revisions] + Chromium[Chromium project] + Firefox[Firefox project] + WebKit[WebKit project] + Semantic{Security-semantic result agrees?} + Difference{Serialization difference only?} + Basis[Focused standards basis + threat analysis + rollback note] + Repair[Repair sanitizer/integration test-first] + ReleaseGate[Rich-clipboard release assurance eligible] + Blocked[Release blocked; unrelated work may continue] + + Head --> Corpus + Head --> Lock + Corpus --> Chromium + Corpus --> Firefox + Corpus --> WebKit + Lock --> Chromium + Lock --> Firefox + Lock --> WebKit + Chromium --> Semantic + Firefox --> Semantic + WebKit --> Semantic + Semantic -->|yes| ReleaseGate + Semantic -->|no| Difference + Difference -->|proven safe standards-permitted difference| Basis --> ReleaseGate + Difference -->|unsafe, unexplained, missing browser, skipped or failed| Repair --> Blocked +``` + +A queued, pending, skipped, cancelled, absent or failed required browser is not passing evidence. Differences are never normalized merely to make engines agree; any admitted difference is a reviewed compatibility artifact. ADR 0016 and Issue #66 own this planned release-assurance decision behind the SafeClipboard integration dependency. + ## Author-to-model proposal sequence ```mermaid @@ -106,6 +142,39 @@ flowchart LR Unsupported or lossy constructs are surfaced by the relevant contract instead of being advertised as lossless round-trip fidelity. +## Envelope identity and host-owned migration routing + +```mermaid +sequenceDiagram + participant Host + participant Inspector as Planned bounded identity inspector + participant Registry as Host migration registry + participant Migration as Host-owned version migration + participant StrictParser as Current-schema strict parser + participant Inkspan + + Host->>Inspector: complete untrusted envelope + Inspector->>Inspector: bounded JSON/UTF-8/duplicate-name/descriptor validation + alt identity invalid + Inspector-->>Host: stable redacted failure + else identity valid + Inspector-->>Host: frozen schemaId + schemaVersion only + Host->>Registry: select authorized migration route + alt current supported identity + Host->>StrictParser: validate current envelope + else registered legacy/future route + Registry->>Migration: run version-specific host migration + Migration-->>Host: candidate current-schema envelope + Host->>StrictParser: strict current-schema validation + else no route + Registry-->>Host: unsupported version; preserve original source + end + StrictParser-->>Inkspan: canonical document only after strict success + end +``` + +The identity result does not contain the document body and does not prove migration, authorization, persistence or durable success. ADR 0015 and Issue #74 define this planned routing aid; the host continues to own schema registry, migration execution, persistence, audit and rollback. + ## Office render and file publication sequence ```mermaid From 2ee50d1a1eed83349097956cd5f24d9afdc9f3ad Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:45:43 +0900 Subject: [PATCH 064/101] docs: trace migration routing and browser release assurance --- docs/TRACEABILITY.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 6f69c16c..06b193b5 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -11,11 +11,13 @@ This record maps durable Inkspan product decisions to authoritative standards, p | Concern | Inkspan decision | Primary authority | Repository evidence | Claim limit | |---|---|---|---|---| | HTTP optimistic concurrency | Durable saves use a host/server-selected strong entity tag; local content digests do not substitute for durable `If-Match` authority | RFC 9110, HTTP Semantics | autosave session tests, `docs/document-autosave.md`, architecture concurrency sequence | Inkspan validates/coordinates local semantics; host owns atomic persistence and authorization | -| JSON envelope grammar | Versioned envelopes use strict JSON handling, duplicate-name defenses, bounded parsing, and explicit schema identity | RFC 8259, JSON | envelope parser/resource-limit tests and package consumers | Current-schema parsing does not imply migration authority for unknown schemas | +| JSON envelope grammar | Versioned envelopes use strict JSON handling, duplicate-name defenses, bounded parsing, and explicit schema identity | RFC 8259; RFC 7493 where interoperable JSON constraints apply | envelope parser/resource-limit tests and package consumers | Current-schema parsing does not imply migration authority for unknown schemas | +| Envelope version routing | A bounded identity-only inspector may identify `schemaId`/`schemaVersion` for dispatch while the current parser stays strict and the host owns migration execution | RFC 8259; RFC 7493; RFC 8785 for canonical current-schema bytes | ADR 0015, Issue #74, envelope tests and planned framework-independent consumer contract | Identifying a schema generation does not validate that generation's document semantics, authorize migration, or prove durable persistence | | Canonical document bytes | Deterministic revision evidence is derived from canonicalized validated document content | RFC 8785, JSON Canonicalization Scheme | revision-evidence, transition-evidence, restore tests | A content digest proves equality only, not actor/time/authorization/durable write | | Provenance semantics | Local transition/release evidence keeps content lineage separate from actor/authorization/durable claims | W3C PROV family | transition evidence, release evidence, canonical data model | Inkspan does not claim complete PROV conformance or host audit provenance | | Accessibility | Native controls, keyboard semantics, shortcut metadata, and host-facing status state support accessible embedding | W3C WCAG 2.2; WAI-ARIA where used | toolbar/accessibility tests, SSR tests, autosave lifecycle data | Component evidence alone is not a full host WCAG conformance claim | -| Browser clipboard behavior | Security-relevant rich HTML handling requires actual paste-pipeline integration and real-engine differential evidence before the rich-clipboard release line | WHATWG HTML parsing; W3C Clipboard API; Playwright browser/project documentation | rich-clipboard unit/integration corpus and planned Chromium/Firefox/WebKit gate | jsdom-only success is not universal browser-engine conformance | +| Browser clipboard behavior | Security-relevant rich HTML handling requires actual paste-pipeline integration and bounded semantic reconstruction before editor state | WHATWG HTML parsing; W3C Clipboard API | rich-clipboard unit/integration corpus and SafeClipboard ADR | jsdom-only success is not universal browser-engine conformance | +| Cross-engine release assurance | The same committed adversarial corpus must run under required Chromium, Firefox, and WebKit projects; only focused standards-grounded safe differences may be admitted | WHATWG HTML Living Standard; W3C Clipboard API and events; Playwright browser/project documentation | ADR 0016, Issue #66, TEST_STRATEGY, UML and planned exact-head browser evidence | The gate is planned behind SafeClipboard integration and does not claim byte-identical browser serialization or branded enterprise-policy coverage | | Editor integration | Public behavior must exercise the actual TipTap/ProseMirror integration path, not an inert extension field or test-only hook | official TipTap and ProseMirror documentation for the locked dependency line | integration tests and package consumers | Inkspan does not claim compatibility with untested major-version integration semantics | | Collaboration | Inkspan provides provider-neutral editor/Yjs bindings; host owns provider lifecycle, room authorization, awareness privacy, persistence and audit | official Yjs/provider documentation plus Inkspan public contract | collaboration tests and architecture ownership matrix | No network-provider or tenant-authorization authority is implied | | Secure development | Security controls are developed test-first, with exact-head scanning/review/package evidence and root-cause regression | NIST SP 800-218 SSDF 1.1 | CI/security/SAST/package/provenance gates, doctoring and regression history | Repository evidence is not a claim of complete SSDF organizational conformance | @@ -24,6 +26,8 @@ This record maps durable Inkspan product decisions to authoritative standards, p ## Current primary references +Bray, T. (Ed.). (2015). *The I-JSON Message Format* (RFC 7493). RFC Editor. https://doi.org/10.17487/RFC7493 + Bray, T. (Ed.). (2017). *The JavaScript Object Notation (JSON) Data Interchange Format* (RFC 8259; STD 90). RFC Editor. https://doi.org/10.17487/RFC8259 Fielding, R., Nottingham, M., & Reschke, J. (Eds.). (2022). *HTTP Semantics* (RFC 9110; STD 97). RFC Editor. https://doi.org/10.17487/RFC9110 @@ -32,13 +36,17 @@ Rundgren, A., Jordan, B., & Erdtman, S. (2020). *JSON Canonicalization Scheme (J Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure Software Development Framework (SSDF) Version 1.1: Recommendations for Mitigating the Risk of Software Vulnerabilities* (NIST SP 800-218). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218 +Web Hypertext Application Technology Working Group. (2026). *HTML Standard: Parsing HTML documents* (Living Standard). Retrieved August 9, 2026, from https://html.spec.whatwg.org/multipage/parsing.html + +World Wide Web Consortium. (2026, June 24). *Clipboard API and events* (W3C Working Draft). https://www.w3.org/TR/2026/WD-clipboard-apis-20260624/ + World Wide Web Consortium. (2024, December 12). *Web Content Accessibility Guidelines (WCAG) 2.2*. https://www.w3.org/TR/WCAG22/ World Wide Web Consortium. (2013). *PROV-DM: The PROV Data Model*. https://www.w3.org/TR/prov-dm/ -Microsoft. (n.d.). *Browsers*. Playwright documentation. https://playwright.dev/docs/browsers +Microsoft. (n.d.). *Browsers*. Playwright documentation. Retrieved August 9, 2026, from https://playwright.dev/docs/browsers -Microsoft. (n.d.). *Projects*. Playwright documentation. https://playwright.dev/docs/test-projects +Microsoft. (n.d.). *Projects*. Playwright documentation. Retrieved August 9, 2026, from https://playwright.dev/docs/test-projects ## Research-backed concurrency rationale From 6532c53d012e150baf20482e1adf1f8ada7da03d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:47:00 +0900 Subject: [PATCH 065/101] test(docs): require evidence-model coverage for planned decisions --- ...canonicalDocumentationDecisionCoverage.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/canonicalDocumentationDecisionCoverage.test.ts b/src/canonicalDocumentationDecisionCoverage.test.ts index b9494d70..0438dac2 100644 --- a/src/canonicalDocumentationDecisionCoverage.test.ts +++ b/src/canonicalDocumentationDecisionCoverage.test.ts @@ -67,4 +67,19 @@ describe('canonical architecture decision coverage', () => { expect(traceability).toContain('Cross-engine release assurance'); expect(traceability).toContain('RFC 7493'); }); + + it('keeps the conceptual ERD explicit without inventing Inkspan persistence', () => { + const dataModel = repositoryFile('docs/DATA_MODEL.md'); + + for (const marker of [ + 'document_schema_identity', + 'browser_assurance_evidence', + 'browser_difference_allowance', + ]) { + expect(dataModel).toContain(marker); + } + expect(dataModel).toContain('planned value and evidence objects'); + expect(dataModel).toContain('does **not** own an application database'); + expect(dataModel).toContain('physical database ERD'); + }); }); From ec209f00b30827b4990e49878997385dfbf5a4c4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:47:43 +0900 Subject: [PATCH 066/101] docs(erd): model planned migration and browser evidence --- docs/DATA_MODEL.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/DATA_MODEL.md b/docs/DATA_MODEL.md index 178c3d0d..2e47e24b 100644 --- a/docs/DATA_MODEL.md +++ b/docs/DATA_MODEL.md @@ -9,6 +9,7 @@ Inkspan does **not** own an application database in the current architecture. Th ```mermaid erDiagram document_envelope ||--|| document_revision : derives + document_envelope ||--o| document_schema_identity : may_identify editor_session ||--o{ document_revision : observes document_revision ||--o{ document_transition : previous_or_resulting document_revision ||--o{ selection_evidence : binds @@ -20,8 +21,11 @@ erDiagram collaboration_document ||--o{ awareness_state : exposes provider_binding }o--|| host_capability : requires collaboration_document }o--o{ editor_session : coordinates + document_schema_identity }o--|| host_capability : routes_migration_through clipboard_policy ||--o{ document_envelope : constrains_input + clipboard_policy ||--o{ browser_assurance_evidence : verified_by + browser_assurance_evidence ||--o{ browser_difference_allowance : may_admit document_envelope ||--o{ conversion_request : source_for conversion_request ||--o| conversion_artifact : produces @@ -29,6 +33,7 @@ erDiagram conversion_artifact ||--o{ audit_event : host_may_record release_artifact }o--|| release_evidence : verified_by + release_evidence ||--o{ browser_assurance_evidence : may_require release_evidence ||--o{ audit_event : host_or_release_system_records ``` @@ -48,13 +53,23 @@ erDiagram - `release_artifact`: package/wheel/checksum or other expected artifact considered for release. - `release_evidence`: exact-source artifact inventory/digest/provenance/verification evidence used before publication. +## Planned value and evidence objects + +The following **planned value and evidence objects** make already accepted future boundaries visible in the conceptual ERD without claiming that their APIs or persistence exist on protected `main`: + +- `document_schema_identity`: proposed frozen identity-only routing metadata containing the bounded envelope `schemaId` and `schemaVersion`. It contains no document body and does not validate unknown-version document semantics. ADR 0015 and Issue #74 define the planned public routing aid; the host owns migration selection/execution and persistence. +- `browser_assurance_evidence`: proposed exact-head release evidence from the same committed rich-clipboard corpus executed in required Chromium, Firefox, and WebKit projects. It records bounded public fixture/corpus, browser-revision, package-lock, platform and source identity rather than tenant clipboard data. +- `browser_difference_allowance`: proposed reviewed explanation for one standards-permitted browser serialization difference. It is attached only to focused evidence with threat analysis and rollback; it never acts as a generic normalization rule or approval substitute. + +These values may remain ephemeral or release-artifact metadata. Their presence in the logical model does not create an Inkspan application database or transfer host authority. + ## Host-owned conceptual entities and boundaries - `durable_validator`: host/server-selected strong HTTP entity tag used for durable compare-and-swap. Inkspan validates/coordinates the value but does not select durable server state. - `collaboration_document`: host-owned Yjs-compatible collaborative document state supplied to Inkspan. Room identity, tenant membership, persistence and retention remain host responsibilities. - `awareness_state`: host/provider-governed ephemeral collaboration presence metadata. It can contain sensitive tenant information and is not authorization evidence. - `provider_binding`: host-created connection/binding between an Inkspan collaboration adapter and a collaboration provider/document. Inkspan does not own credentials, reconnect policy, provider creation/destruction, or durable update storage. -- `host_capability`: conceptual set of explicitly supplied host capabilities such as durable save callback, authenticated API, collaboration provider, external model proposal surface, file-output authority, or naruon panel composition. Absence of a capability means Inkspan must not invent it. +- `host_capability`: conceptual set of explicitly supplied host capabilities such as durable save callback, authenticated API, collaboration provider, external model proposal surface, file-output authority, migration registry, or naruon panel composition. Absence of a capability means Inkspan must not invent it. - `audit_event`: host/release-system owned durable event for actor, authorization, durable save, migration, provider, security, or release activity. Inkspan local revisions/transitions/snapshots do not substitute for authenticated durable audit records. ## Ownership and lifecycle matrix @@ -62,6 +77,7 @@ erDiagram | Entity | Current physical persistence owner | Typical lifecycle | Contains complete document body? | Authority claim | |---|---|---|---|---| | `document_envelope` | host if persisted | document revision | yes | deterministic document value only | +| `document_schema_identity` | none required; planned | one routing inspection | no | schema-route metadata only | | `document_revision` | local or host metadata by policy | derived per exact content | no | equality only | | `editor_session` | none required | mounted editor runtime | may reference local state | no auth/session authority | | `document_transition` | none required; host may store | change evidence | no | content-lineage evidence only | @@ -76,6 +92,8 @@ erDiagram | `conversion_request` | none required | one deterministic conversion | may reference/contain requested source content | conversion intent only | | `conversion_artifact` | caller/host filesystem or artifact store | successful render/export | yes, rendered form | successful deterministic output only | | `render_warning` | none required; host may log under policy | conversion result | no by default | warning/limitation only | +| `browser_assurance_evidence` | release system if retained; planned | one exact-head browser gate | public fixture metadata only | release assurance evidence only | +| `browser_difference_allowance` | release system if retained; planned | focused engine difference | no tenant content | reviewed safe-difference rationale only | | `audit_event` | host/release system | durable operational history | should avoid complete body unless policy requires | authenticated host/release evidence | | `release_artifact` | release system | build/release | package content | candidate artifact only | | `release_evidence` | release system | exact-head publication | no tenant document content | artifact/source verification only | @@ -85,18 +103,20 @@ erDiagram The current Inkspan runtime does not create a tenant database, but products embedding it depend on temporal/version provenance boundaries: - `document_envelope` carries an explicit schema/version contract; unknown versions require host-owned migration routing rather than permissive parsing. +- the planned `document_schema_identity` may expose only bounded routing metadata; it never validates or migrates the unsupported document body and never creates a durable version claim. - `document_revision`, selection, transition, and autosave evidence bind to one exact content state; they do not add actor/time/tenant claims not present in the source contract. - `durable_validator` is temporally ordered by the host's atomic persistence service and must advance only after validated durable success. - `collaboration_document`, `provider_binding`, `awareness_state`, `host_capability`, and `audit_event` can be tenant-scoped in a host, but Inkspan does not define or infer that tenant key. +- `browser_assurance_evidence` and any focused `browser_difference_allowance` bind to one exact source, corpus, package lock and browser revision set; predecessor or different-browser evidence does not transfer silently. - `release_evidence` binds package artifacts to one exact protected source generation; predecessor evidence does not transfer after source movement. ## Privacy and minimum-disclosure rules -Ordinary lifecycle/selection/transition evidence should remain document-free. Revision/entity tags, provider metadata, awareness state, and host identifiers can still be tenant-confidential metadata and must not become public high-cardinality metric labels or unauthenticated logs. Complete document envelopes, Yjs state, conversion inputs/artifacts, prompts/model outputs, credentials, and host authorization claims follow the host's purpose, encryption, retention, and access policy. +Ordinary lifecycle/selection/transition/schema-identity evidence should remain document-free. Revision/entity tags, provider metadata, awareness state, schema identity, browser evidence and host identifiers can still be tenant-confidential or release-sensitive metadata and must not become public high-cardinality metric labels or unauthenticated logs without an explicit policy. Complete document envelopes, Yjs state, conversion inputs/artifacts, prompts/model outputs, credentials, and host authorization claims follow the host's purpose, encryption, retention, and access policy. ## Persistence non-applicability and future change -No Inkspan-owned relational schema is required by the current architecture, so no physical database ERD or migration set is invented here merely to satisfy documentation completeness. If Inkspan later introduces durable persistence, that is a material architecture change requiring: +No Inkspan-owned relational schema is required by the current architecture, so no physical database ERD or migration set is invented here merely to satisfy documentation completeness. Planned identity-routing and browser-assurance values are logical API/evidence objects, not database tables. If Inkspan later introduces durable persistence, that is a material architecture change requiring: 1. an Accepted ADR defining why persistence moved into Inkspan; 2. a physical ERD with descriptive multiword `snake_case` object names; From 0c5720ce2ca07ebeee1a6e3545be79f0c60555e2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 21:53:10 +0900 Subject: [PATCH 067/101] docs(changelog): record canonical decision coverage --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c5949fb..ebf17e89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,8 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ## [Unreleased] ### Documentation -- Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and fourteen linked architecture decision records without inventing Inkspan-owned persistence or host authority -- Added a machine-checkable canonical-documentation contract that keeps required files, ADR index links and completeness, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, and host-vs-Inkspan authority boundaries synchronized +- Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and sixteen linked architecture decision records without inventing Inkspan-owned persistence or host authority; the newest decisions make envelope schema identity/host-owned migration routing and cross-engine browser-semantic release assurance first-class while keeping their implementations explicitly planned +- Added machine-checkable canonical-documentation decision coverage that keeps required files, ADR index links and completeness, migration-routing and browser-assurance UML/data-model/traceability evidence, physical-ERD non-applicability, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, and host-vs-Inkspan authority boundaries synchronized - Added an authoritative standalone and modular MSA architecture contract with reviewable deployment, optimistic-concurrency, data-ownership, security, and acquisition-evidence diagrams and tables - Added a beginner-readable naruon compose and ui.panel integration guide covering narrow client hydration, server-selected strong validators, accessible conflict handling, host-owned Yjs lifecycle, contextual-orchestrator boundaries, and local-versus-shareable evidence - Added an opaque editing-context remount for the complete editor and autosave example, latest-generation asynchronous capture ordering, encoded document path segments, redacted recovery status, and lazy state-owned session identity to prevent cross-document state reuse From 971196a29b11cce049dbacd215f9638ec0a1202f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 22:06:42 +0900 Subject: [PATCH 068/101] test(docs): require work-conserving maintenance guidance --- ...nonicalDocumentationDecisionCoverage.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/canonicalDocumentationDecisionCoverage.test.ts b/src/canonicalDocumentationDecisionCoverage.test.ts index 0438dac2..2c3b62c9 100644 --- a/src/canonicalDocumentationDecisionCoverage.test.ts +++ b/src/canonicalDocumentationDecisionCoverage.test.ts @@ -82,4 +82,21 @@ describe('canonical architecture decision coverage', () => { expect(dataModel).toContain('does **not** own an application database'); expect(dataModel).toContain('physical database ERD'); }); + + it('keeps autonomous maintenance work-conserving without making it product runtime', () => { + const agents = repositoryFile('AGENTS.md'); + const claude = repositoryFile('CLAUDE.md'); + const fitness = repositoryFile('docs/DOCUMENTATION_FITNESS.md'); + + for (const guidance of [agents, claude]) { + expect(guidance).toContain('work-conserving'); + expect(guidance).toContain('blocked PR blocks only that lane'); + expect(guidance).toContain('status report'); + expect(guidance).toContain('external scheduler'); + } + + expect(fitness).toContain('Autonomous maintenance governance'); + expect(fitness).toContain('out_of_scope'); + expect(fitness).toContain('external scheduler'); + }); }); From 4097193b5848b0d8e51033443d63378b027d2c27 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 22:07:00 +0900 Subject: [PATCH 069/101] docs(agents): preserve work-conserving maintenance discipline --- AGENTS.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 729ae2d8..108387c3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,14 @@ Inkspan owns deterministic editor/conversion behavior, versioned document/eviden Do not infer shipped behavior from conversation history, PR bodies, model output, or predecessor-head evidence. Keep Proposed/Active-PR behavior distinct from implementation on Protected `main`, preserve fail-closed security and deterministic conversion boundaries, and update the smallest affected canonical documents plus tests when a durable contract changes. +## Autonomous maintenance execution discipline + +When an external scheduler or autonomous maintainer is operating on Inkspan, repository work is **work-conserving**: after every mutation, proof, merge, closure, review/check observation, or defer decision, select the next highest-value safe Inkspan action while practical execution budget remains. A blocked PR blocks only that lane; queued CI, reviewer latency, provider cooldown, a read-only dependency, or missing approval must not freeze unrelated work. + +A status report, prompt update, documentation assessment, green check, PR creation, review request, or one completed product slice is an intermediate result rather than repository completion while another safe action exists. Before ending an autonomous run, re-scan open PRs/issues, protected `main`, changed branches, reviews/checks/security findings, documentation fitness, release evidence, and buyer-visible gaps; continue if any executable item remains. + +The external scheduler remains the execution authority for cadence and run continuation. These repository instructions define Inkspan-specific writer, evidence, product, and safety discipline only; they do not make scheduling or autonomous orchestration an Inkspan runtime capability. + ## Code-owner review gates — disabled (on hold) As of 2026-08-04, code-owner review requirements (`require_code_owner_reviews` in branch From 21d772ba8736a0bdcc5dff3b43bd03310bc70045 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 22:07:12 +0900 Subject: [PATCH 070/101] docs(agents): make autonomous execution work-conserving --- CLAUDE.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index de8315c7..6b725289 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,6 +27,14 @@ For architectural changes, update the smallest affected canonical records and AD A queued, pending, cancelled, skipped-required, stale-head, predecessor-head, status-only, comment-only, author-only, or synthetic-merge result is not acceptance evidence. Formal review, automated review, repository checks, host authorization, and release evidence remain distinct authorities. +## Autonomous maintenance execution discipline + +When an external scheduler or autonomous maintainer drives Inkspan work, execution is **work-conserving**. After each mutation, proof, merge, closure, review/check observation, or defer decision, choose the next highest-value safe Inkspan item while practical execution budget remains. A blocked PR blocks only that lane; do not let queued CI, reviewer latency, provider cooldown, a read-only dependency, or missing approval freeze unrelated source, documentation, operability, or product work. + +Do not use a status report, prompt update, documentation assessment, green check, PR creation, review request, or one completed product slice as a stopping condition while another safe action exists. Before ending an autonomous run, re-scan open PRs/issues, protected `main`, changed branches, review/check/security evidence, canonical-document fitness, release readiness, and buyer-visible gaps; continue when an executable item remains. + +The external scheduler remains the execution authority for cadence and continuation. This file constrains repository-specific writer/evidence/product/safety behavior and does not make scheduling or autonomous orchestration part of Inkspan runtime architecture. + ## Integration discipline Inkspan must remain independently usable. naruon and other CWL hosts compose it through narrow host-owned boundaries; they are not required runtime dependencies. Central `.github`, contextual-orchestrator, and other repositories are external bounded contexts and must not be locally patched around when they own a shared control-plane defect. From cf4a6d6945cd016330ac8b77ff5684ebed867321 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 22:07:41 +0900 Subject: [PATCH 071/101] docs: classify autonomous maintenance governance --- docs/DOCUMENTATION_FITNESS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 80637249..efda52bb 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -51,6 +51,7 @@ Document fitness and implementation maturity are independent. A `present_current | Cross-engine browser-semantic release assurance | ADR 0016, UML, TEST_STRATEGY, TRACEABILITY and Issue #66 | `present_current` | Differential Chromium/Firefox/WebKit release gate is `planned` behind PR #65 | Browser-realistic security assurance is a durable release decision even though its implementation remains dependency-ordered future work. | | TRACEABILITY | `docs/TRACEABILITY.md` | `present_current` | Links standards/research/requirements to decisions and evidence with scoped claims | Acquisition reviewers can distinguish evidence from aspiration. | | Contributor/agent authority | `AGENTS.md`, `CLAUDE.md`, `docs/README.md` | `present_current` | Protected-main-first decision discipline | Agents are directed back to the same canonical graph rather than parallel private memory. | +| Autonomous maintenance governance | `AGENTS.md`, `CLAUDE.md` plus the external scheduler | `present_current` | `out_of_scope` as Inkspan runtime behavior; the external scheduler owns cadence/continuation | Work-conserving execution, lane-local waiting, no-report-as-completion, and the scheduler-vs-product authority boundary are reconstructable without pretending automation is an Inkspan API. | ## Conversation-to-GitHub reconciliation @@ -69,7 +70,7 @@ The canonical graph must retain durable product decisions from the project conve - real Chromium/Firefox/WebKit differential evidence as a release gate for browser-semantic clipboard security rather than a jsdom conformance claim; and - exact-head/package/security/provenance/release evidence as separate authorities from comments, model verdicts and historical checks. -Autonomous commercial-maintenance scheduling and the no-early-stop execution discipline are **control-plane governance, not a shipped Inkspan product capability**. The scheduler prompt is the execution authority for that loop; repository guidance records writer leases, evidence hierarchy and protected-main authority without pretending the automation prompt is a runtime API or architectural feature. +Autonomous commercial-maintenance scheduling and the no-early-stop execution discipline are **control-plane governance, not a shipped Inkspan product capability**. The external scheduler is the execution authority for cadence and continuation; repository guidance records writer leases, work-conserving queue behavior, lane-local waiting, evidence hierarchy and protected-main authority without pretending the automation prompt is a runtime API or architectural feature. Where an older conversation, PR body, or plan conflicts with Protected `main`, it is historical rather than canonical. Where a requirement is only on an active PR, this documentation may describe it as `implemented_on_active_pr` but never as shipped. From 1160eb277ecdf47f809dfa44edeb18a5c298b067 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 22:08:26 +0900 Subject: [PATCH 072/101] docs: record work-conserving maintainer governance --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebf17e89..4d262e65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ### Documentation - Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and sixteen linked architecture decision records without inventing Inkspan-owned persistence or host authority; the newest decisions make envelope schema identity/host-owned migration routing and cross-engine browser-semantic release assurance first-class while keeping their implementations explicitly planned -- Added machine-checkable canonical-documentation decision coverage that keeps required files, ADR index links and completeness, migration-routing and browser-assurance UML/data-model/traceability evidence, physical-ERD non-applicability, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, and host-vs-Inkspan authority boundaries synchronized +- Added machine-checkable canonical-documentation decision coverage that keeps required files, ADR index links and completeness, migration-routing and browser-assurance UML/data-model/traceability evidence, physical-ERD non-applicability, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, host-vs-Inkspan authority boundaries, and work-conserving autonomous-maintenance guidance synchronized +- Documented work-conserving autonomous-maintenance governance in `AGENTS.md` and `CLAUDE.md`: a blocked PR blocks only its lane, status/report/prompt/documentation milestones are intermediate while safe work remains, and the external scheduler owns cadence rather than becoming an Inkspan runtime capability - Added an authoritative standalone and modular MSA architecture contract with reviewable deployment, optimistic-concurrency, data-ownership, security, and acquisition-evidence diagrams and tables - Added a beginner-readable naruon compose and ui.panel integration guide covering narrow client hydration, server-selected strong validators, accessible conflict handling, host-owned Yjs lifecycle, contextual-orchestrator boundaries, and local-versus-shareable evidence - Added an opaque editing-context remount for the complete editor and autosave example, latest-generation asynchronous capture ordering, encoded document path segments, redacted recovery status, and lazy state-owned session identity to prevent cross-document state reuse @@ -97,4 +98,4 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ### Documentation - Added the autosave architecture and doctoring record with APA 7th references to RFC 9110, RFC 8785, Herlihy and Wing (1990), and ISO/IEC 25010:2023 -- Added an operator guide covering correct durable-base `If-Match` usage, local versus durable ownership, SSR/worker compatibility, observability minimization, and CWL/naruon modular integration boundaries +- Added an operator guide covering correct durable-base `If-Match` usage, local versus durable ownership, SSR/worker compatibility, observability minimization, and CWL/naruon modular integration boundaries \ No newline at end of file From e97b51e48082d696309280e93d86e2c3f2451ac3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 9 Aug 2026 23:11:36 +0900 Subject: [PATCH 073/101] chore(docs): reconcile protected release gate --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d262e65..69e11601 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ## [Unreleased] +### 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 + ### Documentation - Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and sixteen linked architecture decision records without inventing Inkspan-owned persistence or host authority; the newest decisions make envelope schema identity/host-owned migration routing and cross-engine browser-semantic release assurance first-class while keeping their implementations explicitly planned - Added machine-checkable canonical-documentation decision coverage that keeps required files, ADR index links and completeness, migration-routing and browser-assurance UML/data-model/traceability evidence, physical-ERD non-applicability, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, host-vs-Inkspan authority boundaries, and work-conserving autonomous-maintenance guidance synchronized @@ -98,4 +101,4 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ### Documentation - Added the autosave architecture and doctoring record with APA 7th references to RFC 9110, RFC 8785, Herlihy and Wing (1990), and ISO/IEC 25010:2023 -- Added an operator guide covering correct durable-base `If-Match` usage, local versus durable ownership, SSR/worker compatibility, observability minimization, and CWL/naruon modular integration boundaries \ No newline at end of file +- Added an operator guide covering correct durable-base `If-Match` usage, local versus durable ownership, SSR/worker compatibility, observability minimization, and CWL/naruon modular integration boundaries From 04cbd52db8929e0a95b5ec7e00164b047c64c6d3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:11:42 +0900 Subject: [PATCH 074/101] test(docs): require protected security disclosure decision --- ...anonicalDocumentationDecisionCoverage.test.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/canonicalDocumentationDecisionCoverage.test.ts b/src/canonicalDocumentationDecisionCoverage.test.ts index 2c3b62c9..27baa3c6 100644 --- a/src/canonicalDocumentationDecisionCoverage.test.ts +++ b/src/canonicalDocumentationDecisionCoverage.test.ts @@ -12,22 +12,26 @@ const migrationAdr = 'docs/adr/0015-envelope-schema-migration-routing.md'; const browserAssuranceAdr = 'docs/adr/0016-cross-engine-browser-assurance.md'; +const securityDisclosureAdr = + 'docs/adr/0017-security-disclosure-lifecycle.md'; describe('canonical architecture decision coverage', () => { - it('requires durable ADRs for migration routing and browser-semantic release assurance', () => { - for (const path of [migrationAdr, browserAssuranceAdr]) { + it('requires durable ADRs for migration routing, browser assurance, and security disclosure', () => { + for (const path of [migrationAdr, browserAssuranceAdr, securityDisclosureAdr]) { expect(existsSync(resolve(process.cwd(), path)), path).toBe(true); } const index = repositoryFile('docs/adr/README.md'); expect(index).toContain('0015-envelope-schema-migration-routing.md'); expect(index).toContain('0016-cross-engine-browser-assurance.md'); + expect(index).toContain('0017-security-disclosure-lifecycle.md'); expect(index).toContain('Envelope schema identity and host-owned migration routing'); expect(index).toContain('Cross-engine browser-semantic release assurance'); + expect(index).toContain('Security disclosure lifecycle and coordinated vulnerability handling'); }); it('keeps the new decisions complete enough for acquisition review', () => { - for (const path of [migrationAdr, browserAssuranceAdr]) { + for (const path of [migrationAdr, browserAssuranceAdr, securityDisclosureAdr]) { const adr = repositoryFile(path); expect(adr).toContain('Status: Proposed'); for (const heading of [ @@ -47,17 +51,19 @@ describe('canonical architecture decision coverage', () => { } }); - it('distinguishes documentation completeness from planned implementation maturity', () => { + it('distinguishes documentation completeness from implementation maturity', () => { const fitness = repositoryFile('docs/DOCUMENTATION_FITNESS.md'); expect(fitness).toContain('Envelope schema identity / migration routing'); expect(fitness).toContain('Cross-engine browser-semantic release assurance'); + expect(fitness).toContain('SECURITY disclosure policy'); expect(fitness).toContain('present_current'); + expect(fitness).toContain('implemented_on_protected_main'); expect(fitness).toContain('planned'); expect(fitness).toContain('Issue #74'); expect(fitness).toContain('Issue #66'); }); - it('makes both decision paths reviewable as diagrams and standards traceability', () => { + it('makes both planned decision paths reviewable as diagrams and standards traceability', () => { const uml = repositoryFile('docs/UML.md'); const traceability = repositoryFile('docs/TRACEABILITY.md'); From 053f6c17c9a92d9c2e172e19db1e9b75be1285e5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:12:16 +0900 Subject: [PATCH 075/101] docs(adr): capture protected security disclosure lifecycle --- .../adr/0017-security-disclosure-lifecycle.md | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 docs/adr/0017-security-disclosure-lifecycle.md diff --git a/docs/adr/0017-security-disclosure-lifecycle.md b/docs/adr/0017-security-disclosure-lifecycle.md new file mode 100644 index 00000000..385f20d8 --- /dev/null +++ b/docs/adr/0017-security-disclosure-lifecycle.md @@ -0,0 +1,80 @@ +# ADR 0017: Security disclosure lifecycle and coordinated vulnerability handling + +Status: Proposed + +## Context + +Protected `main` now contains root `SECURITY.md` and its deterministic documentation contract from the independently reviewed security-disclosure line. Inkspan therefore has a shipped repository-native intake and coordinated-disclosure policy rather than an architecture target owned by a separate active PR. The canonical documentation graph must capture the durable decision without rewriting the security policy itself or confusing a protected-main process contract with certification, a bounty, a legal safe-harbor promise, or an operational response-time SLA. + +The policy must remain consistent with Inkspan's product boundary: Inkspan owns its editor, deterministic conversion, package, and release surfaces, while embedding hosts retain their own transport, authentication, authorization, tenancy, durable persistence, credentials, deployment, retention, collaboration-provider authority, and model-use policy. + +## Alternatives considered + +### Keep disclosure guidance only in feature doctoring or PR history + +Rejected. Security researchers and acquisition reviewers need a stable repository-root discovery path; PR bodies and conversation history are not durable product authority. + +### Duplicate the full `SECURITY.md` policy into architecture documents + +Rejected. Duplicated policy prose creates two security authorities that can drift. The root policy remains normative for reporting and supported release lines; this ADR records why that lifecycle and ownership boundary exist. + +### Promise fixed response/remediation SLAs or a bounty as part of the baseline + +Rejected. The repository does not have evidence or organizational authority to guarantee those commitments. Such promises require separately reviewed operational/legal authority and measurable support capacity. + +### Public issue intake for vulnerability details + +Rejected. Public issue content is unsuitable for undisclosed vulnerability details, proof-of-concept payloads, secrets, or customer data. Private GitHub Security Advisory reporting is preferred when available; the bounded public fallback may only request a private contact without vulnerability details. + +## Decision + +1. Root `SECURITY.md` is the canonical vulnerability-reporting and coordinated-disclosure policy for Inkspan. +2. Supported pre-1.0 release lines are derived from actual package manifests and kept under deterministic documentation tests rather than copied as unbound prose. +3. Reporters are directed to GitHub's private vulnerability-reporting / Security Advisory path when available. A public issue may only request a private reporting contact and must not contain vulnerability details, proof-of-concept payloads, secrets, or customer data. +4. Intake requests exact affected version, minimal synthetic reproduction, exploit prerequisites, and minimized evidence sufficient for reproduction. +5. Maintainer handling follows private intake -> exact-version reproduction -> root-cause regression -> bounded fix -> exact-head CI/security/coverage/package/provenance/review evidence -> advisory/CVE coordination when appropriate -> coordinated disclosure. +6. The policy does not claim a response-time SLA, bounty, legal safe harbor, certification, or complete framework conformance. +7. Inkspan's security policy covers Inkspan-owned product/package surfaces. Host-owned identity, transport, tenancy, persistence, deployment, retention, collaboration-provider, and model-policy incidents remain the embedding host's responsibility unless evidence shows an Inkspan defect contributes to the issue. +8. Final published standards remain normative where a newer revision is only draft; draft standards may be tracked as evidence inputs but do not silently replace the final baseline. + +## Consequences + +Security researchers have a stable private intake path and explicit evidence-minimization guidance. Acquisition reviewers can distinguish a documented disclosure process from unsupported certification or SLA claims. The canonical architecture remains single-source: `SECURITY.md` defines the operational reporting policy, this ADR defines the durable decision and boundaries, and doctoring records source/version evidence. + +The repository assumes ongoing maintenance responsibility for keeping supported release rows, GitHub reporting mechanics, standards references, and release evidence synchronized with actual package and repository behavior. + +## Failure and recovery + +If private vulnerability reporting becomes unavailable, the public fallback remains limited to requesting a private contact; sensitive details are not moved into a public issue as a workaround. If package support lines change, deterministic tests must fail until `SECURITY.md` is updated to match the manifests. If GitHub changes the private-reporting workflow, the policy must fail safe toward private contact rather than inventing a nonexistent control. + +If a security-policy change overstates organizational capability, certification, legal protection, or response guarantees, revert the unsupported claim and restore the last evidence-backed policy while a separately authorized decision is reviewed. Active vulnerability handling should not be blocked by documentation repair when a safe private channel exists. + +## Security and privacy impact + +The decision reduces accidental disclosure by preferring private intake and minimizing submitted evidence. Public issue fallback explicitly excludes vulnerability details, secrets, customer content, and proof-of-concept payloads. Reproduction should use synthetic/minimized data wherever possible, with exact affected versions and exploit prerequisites recorded separately from unnecessary tenant content. + +The policy itself does not grant authorization to test third-party or customer systems and does not expand maintainer access to host-owned data or credentials. + +## Compatibility and migration + +This is a repository-process contract and does not change runtime APIs, stored document schemas, package formats, database objects, host integrations, or deployment topology. Existing users continue to consume the same product packages. Future security-policy changes remain backward-compatible when possible; any new support commitment or reporting mechanism requires synchronized documentation tests and, when material, a superseding ADR. + +## Verification + +Protected `main` contains root `SECURITY.md`, deterministic tests binding its supported release rows to package manifests, and doctoring that records ISO/IEC 29147:2018, ISO/IEC 30111:2019, NIST SP 800-218 SSDF Version 1.1, the draft-status boundary for the later SSDF revision, and GitHub private-reporting/coordinated-disclosure guidance. The protected merge of the security-disclosure line is implementation evidence; this documentation branch must not downgrade it to an active-PR claim. + +Canonical documentation tests require this ADR, its index entry, and `docs/DOCUMENTATION_FITNESS.md` to classify the root security disclosure policy as `present_current` with `implemented_on_protected_main` maturity. + +## Rollback or supersession + +Rollback of this ADR does not remove protected `SECURITY.md`; the root policy remains authoritative until separately changed through normal protected review. A future ADR may supersede this decision if Inkspan adopts a materially different reporting platform, formal support SLA, bounty program, legal safe-harbor policy, or organization-wide security-response authority. Supersession must preserve a discoverable private vulnerability-reporting path during migration. + +## References + +International Organization for Standardization. (2018). *Information technology — Security techniques — Vulnerability disclosure* (ISO/IEC 29147:2018). + +International Organization for Standardization. (2019). *Information technology — Security techniques — Vulnerability handling processes* (ISO/IEC 30111:2019). + +Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure Software Development Framework (SSDF) Version 1.1: Recommendations for Mitigating the Risk of Software Vulnerabilities* (NIST SP 800-218). National Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218 + +GitHub. (n.d.). *About repository security advisories*. GitHub Docs. From af7ac059790792d4a0585d2805ec8eaa96f32282 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:12:34 +0900 Subject: [PATCH 076/101] docs(adr): index security disclosure lifecycle --- docs/adr/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index 88a5c403..2f984d91 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -22,6 +22,7 @@ This index records durable architectural decisions. Protected-main implementatio | [0014](0014-local-assets-font-licensing.md) | Proposed | Local assets and font-licensing boundary | | [0015](0015-envelope-schema-migration-routing.md) | Proposed | Envelope schema identity and host-owned migration routing | | [0016](0016-cross-engine-browser-assurance.md) | Proposed | Cross-engine browser-semantic release assurance | +| [0017](0017-security-disclosure-lifecycle.md) | Proposed | Security disclosure lifecycle and coordinated vulnerability handling | ## Decision discipline @@ -29,7 +30,7 @@ This index records durable architectural decisions. Protected-main implementatio - **Accepted**: integrated into protected `main` with the applicable verification evidence. - **Superseded**: retained for historical traceability but explicitly replaced by a later ADR. -An ADR cannot promote an unmerged feature to shipped behavior. When a decision changes materially, add or supersede an ADR rather than silently rewriting history. +An ADR cannot promote an unmerged feature to shipped behavior. When a decision changes materially, add or supersede an ADR rather than silently rewriting history. A Proposed ADR may document a decision whose underlying implementation already exists on protected `main`; its own status remains Proposed until this ADR file is integrated, while implementation maturity is recorded separately in the canonical fitness/traceability records. ## ADR quality requirements From 93021e30aeaef0fe497ac2049f35c2276090d49e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:13:03 +0900 Subject: [PATCH 077/101] docs(fitness): recognize protected security disclosure policy --- docs/DOCUMENTATION_FITNESS.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index efda52bb..b76b74e8 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -38,11 +38,11 @@ Document fitness and implementation maturity are independent. A `present_current | TRD | `docs/TRD.md` | `present_current` | Same mixed maturity discipline; Protected `main` remains runtime authority | Technical invariants, failure semantics, package boundaries and release evidence are reconstructable. | | ARCHITECTURE | `ARCHITECTURE.md` | `present_current` | `implemented_on_protected_main` for the bounded standalone/modular architecture | Host-vs-Inkspan authority and modular CWL composition are explicit. | | Public/API/schema/plugin contracts | `docs/CONTRACTS.md` | `present_current` | Protected-main contracts plus explicitly proposed extensions | Integration authority and degraded behavior are not hidden in implementation details. | -| ADR | `docs/adr/README.md` and detailed ADRs | `present_current` | Decisions distinguish current, proposed and future work | Alternatives, consequences, recovery, migration, verification and supersession are reviewable. | +| ADR | `docs/adr/README.md` and detailed ADRs | `present_current` | Decisions distinguish current, proposed and future work; ADR 0017 records the protected security-disclosure lifecycle without duplicating its root policy | Alternatives, consequences, recovery, migration, verification and supersession are reviewable. | | UML | `docs/UML.md` | `present_current` | Diagrams include protected-main and clearly proposed flows | Component, sequence, state, deployment, degraded-mode and authority flows are visible as diagram-as-code. | | DATA_MODEL / ERD | `docs/DATA_MODEL.md` | `present_current` | Current logical evidence/domain model; host persistence remains outside Inkspan | The model distinguishes document/evidence/conversion/release values from host-owned entities. | | physical relational ERD | none by design | `not_applicable` | `out_of_scope` while Inkspan owns no application database | No fake database is invented merely to satisfy an ERD checklist; a physical ERD becomes mandatory if persistence authority moves into Inkspan. | -| SECURITY disclosure policy | root `SECURITY.md` | `owned_by_separate_active_pr` | `implemented_on_active_pr` until protected integration | This branch must not race the separately owned disclosure-policy line. | +| SECURITY disclosure policy | root `SECURITY.md` plus ADR 0017 | `present_current` | `implemented_on_protected_main`; the root policy is protected authority and ADR 0017 records its durable architecture/process decision | Private reporting, evidence minimization, supported release-line binding, ownership limits, coordinated disclosure, and explicit no-SLA/no-certification claim boundaries are reconstructable. | | THREAT_MODEL | `docs/THREAT_MODEL.md` | `present_current` | Covers current and explicitly proposed trust boundaries | Clipboard, Office, SSR/form, Yjs, model, host-authority and supply-chain threats are reconstructable. | | TEST_STRATEGY | `docs/TEST_STRATEGY.md` | `present_current` | Current deterministic evidence plus `planned` cross-engine acceptance where dependency order requires it | Test authority and claim limits are explicit rather than inferred from CI badges. | | OPERABILITY | `docs/OPERABILITY.md` | `present_current` | Current local/product responsibilities plus host-owned recovery boundaries | Conflict, collaboration, conversion and release recovery/rollback ownership are explicit. | @@ -66,6 +66,7 @@ The canonical graph must retain durable product decisions from the project conve - model assistance as untrusted proposed content rather than conversion or persistence authority; - accessibility, keyboard, print/export and document-fidelity evidence boundaries; - host ownership of transport, identity, authorization, tenancy, persistence, credentials, migration, retention, deployment, durable audit and model policy; +- protected-main private vulnerability reporting and coordinated disclosure with explicit evidence-minimization and no-SLA/no-certification boundaries; - strict current-schema parsing plus planned identity-only envelope routing, while migration execution remains host-owned; - real Chromium/Firefox/WebKit differential evidence as a release gate for browser-semantic clipboard security rather than a jsdom conformance claim; and - exact-head/package/security/provenance/release evidence as separate authorities from comments, model verdicts and historical checks. @@ -78,14 +79,14 @@ Where an older conversation, PR body, or plan conflicts with Protected `main`, i The documentation pack itself is substantially complete for acquisition review, but **repository closure is not documentation closure**. The remaining gaps are intentionally represented rather than hidden: -1. The security disclosure policy remains `owned_by_separate_active_pr`; after protected merge, this graph must be reconciled against the actual root `SECURITY.md`. -2. Issue #74 remains `planned`: the identity-only migration-routing API must still be implemented test-first while the current parser remains strict. Its architectural decision is now present rather than hidden in issue prose. -3. Issue #66 remains `planned` behind PR #65: the dependency-locked Chromium/Firefox/WebKit differential suite must still be implemented before the rich-clipboard release line. Its release-assurance decision is now present rather than hidden in issue prose. -4. Active feature branches for autosave observation, revision evidence, SSR/native forms, accessibility, release hardening and runtime compatibility remain `implemented_on_active_pr` until protected integration. +1. Issue #74 remains `planned`: the identity-only migration-routing API must still be implemented test-first while the current parser remains strict. Its architectural decision is now present rather than hidden in issue prose. +2. Issue #66 remains `planned` behind PR #65: the dependency-locked Chromium/Firefox/WebKit differential suite must still be implemented before the rich-clipboard release line. Its release-assurance decision is now present rather than hidden in issue prose. +3. Active feature branches for autosave observation, revision evidence, SSR/native forms, accessibility, and SafeClipboard remain `implemented_on_active_pr` until protected integration. +4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge; the already integrated root `SECURITY.md` is protected authority even while this branch is temporarily behind it. 5. Documentation becoming mergeable or protected-merged is not a reason for the commercial loop to stop; the next safe product, release, security, accessibility or interoperability lane must continue. ## Sufficiency decision -For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Envelope migration routing and cross-engine browser assurance are now explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. The repository security disclosure policy is separately owned and therefore `owned_by_separate_active_pr` rather than duplicated. +For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. The security disclosure lifecycle is `implemented_on_protected_main` and represented by root `SECURITY.md` plus Proposed ADR 0017. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. -No material product architecture decision identified by this review remains only in chat or issue prose. Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph and the separately owned security policy pass their exact-head checks/reviews and normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. +No material product architecture decision identified by this review remains only in chat or issue prose. Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph is reconciled with the latest protected source generation and passes normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. From 70c6e3096fde93646eaea39f69d079b8642a6b69 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:13:47 +0900 Subject: [PATCH 078/101] docs(trd): reconcile protected security disclosure authority --- docs/TRD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/TRD.md b/docs/TRD.md index 01059420..3fae38e0 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -101,8 +101,8 @@ Queued, cancelled, skipped-required, absent, stale-head, predecessor-head, statu ## Security, privacy, and operability dependencies -`docs/THREAT_MODEL.md`, `docs/TEST_STRATEGY.md`, `docs/OPERABILITY.md`, `docs/TRACEABILITY.md`, and the detailed ADR corpus are part of this technical contract. `SECURITY.md` is separately owned by the open security-disclosure PR until that bounded line reaches protected `main`; this branch must not duplicate/race it. +`SECURITY.md`, `docs/THREAT_MODEL.md`, `docs/TEST_STRATEGY.md`, `docs/OPERABILITY.md`, `docs/TRACEABILITY.md`, and the detailed ADR corpus are part of this technical contract. Root `SECURITY.md` is now `implemented_on_protected_main` and is the normative private vulnerability-reporting/coordinated-disclosure policy. ADR 0017 records the durable decision, ownership boundary, claim limits, and recovery/supersession semantics without duplicating the policy text. ## Implemented versus proposed -Protected `main` is the sole implemented baseline. Requirements describing open clipboard, autosave observation, transition/selection evidence, SSR/native-form, accessibility, release-hardening, or security-disclosure PRs are Proposed until merged. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. +Protected `main` is the sole implemented baseline. The security disclosure lifecycle is implemented on protected `main`. Requirements describing open clipboard, autosave observation, transition/selection evidence, SSR/native-form, or accessibility PRs remain Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. From f56cbbfa030e8f8fcbcddf44c75ae10534ed14ea Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:14:12 +0900 Subject: [PATCH 079/101] docs(prd): reconcile protected security disclosure lifecycle --- docs/PRD.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 990c9e70..38dd0116 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -28,6 +28,7 @@ The product promise is: **author, convert, collaborate, and prove document chang 8. Compose Inkspan inside naruon or another CWL host without making those hosts required runtime dependencies for standalone adopters. 9. Offer model-assisted authoring only as host-approved untrusted proposals; deterministic editor/conversion validation remains authoritative. 10. Produce reviewable package, security, compatibility, accessibility, SBOM/provenance, and release evidence tied to one exact protected source head. +11. Give security researchers a discoverable private vulnerability-reporting and coordinated-disclosure path without promising unsupported SLAs, bounties, certification, or legal safe harbor. ## Required outcomes @@ -83,11 +84,19 @@ The product promise is: **author, convert, collaborate, and prove document chang - Application-visible saving/conflict/recovery messages must be derivable from programmatic state without Inkspan prescribing untranslated user-facing copy. - Export/print surfaces must not rely on color alone or inaccessible interaction-only state where the corresponding product surface exists. +### Security disclosure and vulnerability handling + +- Root `SECURITY.md` is the protected-main authority for supported release lines, private vulnerability reporting, minimized evidence, coordinated disclosure, and explicit claim limits. +- Private GitHub vulnerability reporting / Security Advisory intake is preferred when available. Public issues must not contain vulnerability details, proof-of-concept payloads, secrets, or customer data; they may only request a private reporting route when necessary. +- Supported pre-1.0 security lines remain bound to package manifests by deterministic tests rather than copied as unverified prose. +- The policy does not promise a response-time SLA, bounty, legal safe harbor, certification, or complete secure-development-framework conformance without separate evidence and authority. +- Host-owned incidents remain host responsibilities unless an Inkspan-owned defect contributes to the issue. + ## Non-goals Inkspan is not an identity provider, tenant database, durable document store, collaboration authorization server, deployment platform, credential manager, retention engine, model router, durable audit service, application migration owner, or merge/release authority for host products. -Inkspan does not promise universal HTML/Office round-trip fidelity, arbitrary executable document content, implicit network fetching, model-generated content as trusted source, or silent migration of unknown document schemas. +Inkspan does not promise universal HTML/Office round-trip fidelity, arbitrary executable document content, implicit network fetching, model-generated content as trusted source, silent migration of unknown document schemas, a security bounty, legal safe harbor, fixed vulnerability-response SLA, or certification from repository documentation alone. ## Security and privacy requirements @@ -95,6 +104,7 @@ Inkspan does not promise universal HTML/Office round-trip fidelity, arbitrary ex - Active or hidden rich content must not bypass the supported semantic clipboard policy. - Spreadsheet formula-significant input must not silently become executable formulas unless a future explicit trusted formula contract says otherwise. - Document bodies, revision/entity tags, provider metadata, tenant identifiers, prompts, and model outputs must not enter generic public metrics or unauthenticated logs. +- Vulnerability reporting must prefer private channels and minimized/synthetic evidence; public fallback must not disclose vulnerability details, secrets, proof-of-concept payloads, or customer data. - Host applications remain responsible for authentication, authorization, CSRF, tenant isolation, persistence, encryption, retention, audit storage, provider admission, and external-model policy. ## Reliability and operability requirements @@ -104,11 +114,12 @@ Inkspan does not promise universal HTML/Office round-trip fidelity, arbitrary ex - Async revision/selection capture binds to one immutable editor state. - Conversion/publication never reports a partial artifact as successful output. - Package/release operations fail closed on stale source, ambiguous artifact inventory, digest mismatch, missing required evidence, or stale review/check state. +- Security policy support rows and reporting mechanics must remain synchronized with package manifests and current repository capabilities. - Boundary-specific rollback must preserve canonical document readability and host-owned durable state. ## Packaging and acquisition acceptance -A release is acceptable only from an exact integrated protected head with applicable CI/security checks, exact owned production statement/branch/function/line coverage, complete public docstrings where required, package-consumer compatibility, real browser/document-fidelity evidence, accessibility evidence, SBOM/provenance/reproducibility, zero valid unresolved findings, required independent non-author review, rollback guidance, and verified published artifacts. +A release is acceptable only from an exact integrated protected head with applicable CI/security checks, exact owned production statement/branch/function/line coverage, complete public docstrings where required, package-consumer compatibility, real browser/document-fidelity evidence, accessibility evidence, SBOM/provenance/reproducibility, zero valid unresolved findings, actually required independent non-author review, rollback guidance, and verified published artifacts. Shareable acquisition evidence excludes production tenant content and credentials. Protected `main`, exact-head machine evidence, formal reviews, and canonical product documentation outrank historical PR bodies, comments, local-only results, or predecessor-head status. @@ -116,4 +127,4 @@ 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. -Current open development lines include richer browser-verified clipboard assurance, lifecycle observation, document-transition/revision evidence, SSR/native-form integration, accessibility metadata, release hardening, and security disclosure documentation. Their detail is useful design evidence but remains Proposed until merged. A future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. +The root security disclosure lifecycle is implemented on protected `main`. Current open development lines include richer browser-verified clipboard assurance, lifecycle observation, document-transition/revision evidence, SSR/native-form integration, accessibility metadata, and canonical documentation reconciliation. Their detail is useful design evidence but remains Proposed until merged. A future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. From c859793a3ed7d8553b36deb13fb56be69905050e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:14:42 +0900 Subject: [PATCH 080/101] docs(index): recognize protected security disclosure authority --- docs/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 85ee5a56..b5a783d6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ This directory is the discoverable index for Inkspan's product, technical, secur | Document | Authority | | --- | --- | | [`../ARCHITECTURE.md`](../ARCHITECTURE.md) | Current protected-main implementation architecture and bounded-context ownership | +| [`../SECURITY.md`](../SECURITY.md) | Protected-main private vulnerability reporting, supported security lines, coordinated disclosure, and claim limits | | [`DOCUMENTATION_FITNESS.md`](DOCUMENTATION_FITNESS.md) | Acquisition completeness matrix, implementation maturity, deliberate non-applicability and remaining canonical gaps | | [`PRD.md`](PRD.md) | Product users, jobs, buyer outcomes, non-goals, acceptance and claim boundaries | | [`TRD.md`](TRD.md) | Technical invariants, runtime boundaries, failure semantics and release evidence | @@ -19,9 +20,9 @@ This directory is the discoverable index for Inkspan's product, technical, secur | [`TEST_STRATEGY.md`](TEST_STRATEGY.md) | Unit/integration/browser/Office/security/accessibility/package evidence strategy | | [`OPERABILITY.md`](OPERABILITY.md) | Failure handling, recovery, incident ownership, rollback and release operations | | [`TRACEABILITY.md`](TRACEABILITY.md) | Requirements/standards/research-to-decision/test evidence traceability | -| [`adr/README.md`](adr/README.md) | Status-bearing architectural decision index | +| [`adr/README.md`](adr/README.md) | Status-bearing architectural decision index, including ADR 0017 for the protected security-disclosure lifecycle | -The root `SECURITY.md` is the disclosure-policy authority once that separately owned bounded change reaches protected `main`; this index must not duplicate or race an active security-policy branch. `CHANGELOG.md` records shipped/reviewable change history, while `AGENTS.md` and `CLAUDE.md` point contributors back to this canonical graph rather than becoming parallel architecture specifications. +Root `SECURITY.md` is now implemented on protected `main` and remains the normative reporting/disclosure policy. ADR 0017 records the durable architecture/process decision and ownership/claim boundaries without duplicating policy prose. `CHANGELOG.md` records shipped/reviewable change history, while `AGENTS.md` and `CLAUDE.md` point contributors back to this canonical graph rather than becoming parallel architecture specifications. ## Status discipline From 7d6b7c810a917ec3e444221a54a9b0e726212f9b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:15:07 +0900 Subject: [PATCH 081/101] chore(docs): reconcile protected security policy --- SECURITY.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..43504a4e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,71 @@ +# Security Policy + +Inkspan treats vulnerability reporting and handling as part of the product contract. Please use a private channel for suspected security vulnerabilities so maintainers can reproduce, remediate, and coordinate disclosure before exploit details become public. + +## Supported releases + +Inkspan is still pre-1.0, so security support follows the newest released line rather than every historical minor release. + +| Surface | Actively supported security line | Notes | +| --- | --- | --- | +| `@contextualwisdomlab/cwl-editor` | latest released `0.5.x` | Security fixes target the newest released editor line. Older pre-1.0 releases may be superseded rather than backported unless a coordinated advisory requires a bounded backport. | +| `inkspan-office` | latest released `0.1.x` | Security fixes target the newest released Office renderer line and its deterministic packaged artifacts. | + +Unreleased branches and pull requests are development evidence, not supported releases. A finding against an unreleased head is still useful and should be reported privately, but support and disclosure decisions are made against affected released artifacts as well as the development fix. + +A future stable release may define a broader support window. Until then, this table is the public support contract; an enterprise support agreement may define additional maintained versions separately. + +## Reporting a vulnerability + +1. Open the repository **Security** area. If GitHub shows **Report a vulnerability**, use that private reporting form. It creates a private GitHub Security Advisory discussion with the maintainers. +2. If **Report a vulnerability** is unavailable, create a public issue that only asks for a private security contact without disclosing the vulnerability. Do not include vulnerability details, proof-of-concept payloads, secrets, or customer data in a public issue. +3. Keep technical details in the resulting private channel until coordinated disclosure is agreed or the maintainers publish an advisory. + +A useful report includes, when known: + +- the exact affected version, package, entry point, and platform; +- the security boundary or invariant that can be violated; +- a minimal reproduction using synthetic data and the smallest safe proof of impact; +- expected behavior and observed behavior; +- exploit prerequisites and whether interaction, authentication, or a particular host configuration is required; +- whether the issue is already public or known to another vendor; and +- any proposed remediation or regression condition that may help reproduce the issue. + +Do not send production credentials, access tokens, private tenant identifiers, real customer documents, or other unnecessary sensitive material. Replace them with synthetic fixtures whenever possible. If sensitive evidence is essential to establish impact, first establish a private channel and minimize the disclosed material. + +## Scope and ownership boundary + +Reports are in scope when an Inkspan-controlled editor or deterministic conversion surface can violate its documented security boundary, including package parsing/serialization, strict link and image policy, rich-content handling, document-envelope validation, local revision/autosave contracts, provider-neutral collaboration adapters, deterministic Office rendering, packaged artifacts, or Inkspan-owned release evidence. + +Inkspan does not own host-owned transport, authorization, tenant isolation, persistence, credentials, migration, retention, collaboration-provider authorization, downstream deployment policy, or model-use policy. Report a host defect to the host that owns that boundary. An Inkspan flaw that crosses or undermines one of those documented boundaries remains in scope for Inkspan. + +Repository automation and organization-wide security/review infrastructure owned by `ContextualWisdomLab/.github` should be reported against that repository rather than treated as Inkspan runtime behavior. Model-routing defects owned by `ContextualWisdomLab/contextual-orchestrator` likewise belong to that service unless the defect originates in Inkspan's interface contract. + +Security research does not authorize access to third-party data, destructive testing, service degradation, credential theft, social engineering, or testing systems you do not own or have explicit permission to test. + +## Vulnerability handling lifecycle + +For a credible report, maintainers should: + +1. establish a private case and preserve the reporter's original evidence without copying sensitive payloads into ordinary logs or public CI output; +2. reproduce the issue against the exact affected version and current development head, separating an Inkspan defect from host-owned configuration or infrastructure; +3. assess impact, exploit prerequisites, affected release lines, dependency exposure, and whether other vendors need coordinated disclosure; +4. implement the minimum root-cause fix with a root-cause regression test and any required security, compatibility, packaging, or rollback evidence; +5. verify the exact fix head through exact-head CI, security scanning, coverage, packaging/provenance, and independent review gates that apply to the affected release; +6. prepare a GitHub Security Advisory and request a CVE when appropriate for a publicly distributed vulnerability; +7. coordinate release and disclosure timing around user risk, downstream-vendor needs, and availability of a verified remediation; and +8. publish remediation guidance that identifies affected and fixed versions without exposing private customer data or unnecessary exploit detail. + +A failed, queued, cancelled, stale-head, predecessor-head, or synthetic-merge result is not release evidence. A security fix does not weaken tests, bypass branch protection, manufacture approval, or silently broaden Inkspan into a host authorization or persistence service. + +## Communication expectations + +This public policy does not promise a response-time SLA, remediation deadline, bounty, or payment. Those commitments require an explicit support or disclosure agreement. Maintainers should nevertheless keep the private reporter informed when the report is reproducible, when scope or severity changes materially, when a fix is ready for coordinated validation, and when disclosure timing is decided. + +Coordinated disclosure is preferred over unilateral premature publication because users need a verified remediation path. Reporters are also free to communicate reasonable disclosure expectations in the private case; the final schedule should reflect actual user risk rather than an arbitrary silence period. + +## Standards and claim boundary + +This policy is informed by ISO/IEC 29147 vulnerability disclosure guidance, ISO/IEC 30111 vulnerability-handling guidance, NIST SP 800-218 Secure Software Development Framework (SSDF) Version 1.1, and GitHub's current security-policy and private vulnerability-reporting documentation. The corresponding decision and APA 7 references are recorded in [`docs/doctoring/security-disclosure-lifecycle.md`](docs/doctoring/security-disclosure-lifecycle.md). + +Publishing this policy does not by itself establish ISO certification, complete SSDF conformance, a legal safe harbor, or a contractual service level. Deployed hosts and commercial agreements retain their own incident-response, regulatory, notification, and contractual obligations. From 8613eabe10a78522427d88e040b1208bf3e78e18 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:15:39 +0900 Subject: [PATCH 082/101] test(docs): require integrated security authority in canonical graph --- src/canonicalProductDocumentation.test.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index a18c3717..f01e5c4e 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -11,6 +11,7 @@ const requiredFiles = [ 'CLAUDE.md', 'ARCHITECTURE.md', 'CHANGELOG.md', + 'SECURITY.md', 'docs/README.md', 'docs/DOCUMENTATION_FITNESS.md', 'docs/PRD.md', @@ -37,6 +38,9 @@ const requiredFiles = [ 'docs/adr/0012-spreadsheet-formula-injection.md', 'docs/adr/0013-atomic-file-publication.md', 'docs/adr/0014-local-assets-font-licensing.md', + 'docs/adr/0015-envelope-schema-migration-routing.md', + 'docs/adr/0016-cross-engine-browser-assurance.md', + 'docs/adr/0017-security-disclosure-lifecycle.md', 'src/fonts/OFL.txt', 'src/fonts/NOTICE', 'src/fonts/fonts.css', @@ -64,6 +68,7 @@ describe('canonical product documentation graph', () => { } for (const marker of [ '../ARCHITECTURE.md', + '../SECURITY.md', 'DOCUMENTATION_FITNESS.md', 'PRD.md', 'TRD.md', @@ -147,11 +152,15 @@ describe('canonical product documentation graph', () => { }); it('documents realistic security, test, and release evidence boundaries', () => { + const security = repositoryFile('SECURITY.md'); const threatModel = repositoryFile('docs/THREAT_MODEL.md'); const testStrategy = repositoryFile('docs/TEST_STRATEGY.md'); const traceability = repositoryFile('docs/TRACEABILITY.md'); const contracts = repositoryFile('docs/CONTRACTS.md'); + expect(security).toContain('Report a vulnerability'); + expect(security).toContain('private GitHub Security Advisory'); + expect(security).toContain('does not promise a response-time SLA'); expect(threatModel).toContain('clipboard'); expect(threatModel).toContain('formula'); expect(threatModel).toContain('Yjs'); @@ -188,7 +197,6 @@ describe('canonical product documentation graph', () => { for (const status of [ 'present_current', - 'owned_by_separate_active_pr', 'implemented_on_protected_main', 'implemented_on_active_pr', 'planned', @@ -197,6 +205,7 @@ describe('canonical product documentation graph', () => { expect(fitness).toContain(status); } + expect(fitness).toContain('SECURITY disclosure policy'); expect(fitness).toContain('physical relational ERD'); expect(fitness).toContain('not_applicable'); expect(fitness).toContain('Protected `main`'); @@ -251,4 +260,4 @@ describe('canonical product documentation graph', () => { } } }); -}); \ No newline at end of file +}); From 4274d9e812a769943689c9b48fe9c6a377aaa1ce Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:20:03 +0900 Subject: [PATCH 083/101] docs(adr): align autosave snapshot validator privacy contract --- docs/adr/0004-durable-validator-autosave.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/adr/0004-durable-validator-autosave.md b/docs/adr/0004-durable-validator-autosave.md index 35cd42b3..6e1b67d2 100644 --- a/docs/adr/0004-durable-validator-autosave.md +++ b/docs/adr/0004-durable-validator-autosave.md @@ -17,9 +17,11 @@ Local editor revisions are useful equality evidence but cannot prove a durable s Use a single-flight autosave queue with bounded active/pending work and explicit `idle`, `saving`, `blocked`, `closing`, and `closed` lifecycle state. A durable session accepts and advances only host/server-selected strong HTTP entity tags for compare-and-swap. Conflict or ambiguous save failure blocks progression until explicit recovery. Optional lifecycle observation emits only distinct document-free transitions; construction and no-op operations emit nothing, and observer exceptions are isolated. +`getSnapshot()` is an explicit local coordination API rather than generic diagnostics. Its bounded document-free contract may expose `activeStrongEntityTag`, `pendingStrongEntityTag`, and `lastSavedStrongEntityTag` when those values exist so the host can reason about exact local queue/durable-validator state. These fields remain tenant-confidential equality/concurrency metadata: their presence in an authenticated in-process snapshot does not authorize disclosure, persistence, metrics, logging, or reuse as a public identifier. + ## Consequences -Inkspan can coordinate deterministic local ordering while the host remains the only durable authority. Hosts must implement atomic `If-Match` semantics, authorization, retry policy, and durable reconciliation. UI can observe bounded machine state without polling or receiving document bodies. +Inkspan can coordinate deterministic local ordering while the host remains the only durable authority. Hosts must implement atomic `If-Match` semantics, authorization, retry policy, and durable reconciliation. UI can observe bounded machine state without polling or receiving document bodies. Consumers of `getSnapshot()` must treat validator fields as confidential local state and must not promote them to public telemetry dimensions. ## Failure and recovery @@ -27,16 +29,16 @@ Malformed or weak validators fail closed. Conflict preserves durable uncertainty ## Security and privacy impact -Autosave coordination does not grant authorization or tenant authority. Strong validators and local revisions can be tenant-confidential equality metadata, so snapshots and public diagnostics remain document-free and must not expose validators, credentials, complete document bodies, or private callback failures. +Autosave coordination does not grant authorization or tenant authority. Strong validators and local revisions can be tenant-confidential equality metadata. The explicit in-process `getSnapshot()` contract may expose only the bounded active/pending/last-saved validator fields required for local coordination, while generic diagnostics, public metrics, unauthenticated logs, lifecycle notifications, and ordinary telemetry remain document-free and must never expose validators, credentials, complete document bodies, or private callback failures. Any durable/shared handling is host-authorized, purpose-bound, and minimum-disclosure. ## Compatibility and migration -The public queue/session states, validator grammar, and result contracts are compatibility surfaces. Hosts adopting the durable session supply a valid server-selected strong validator and keep durable retry/conflict policy. Any future lifecycle-state or retention change requires compatibility tests, migration guidance, and a rollback that preserves host durable state. +The public queue/session states, the three optional validator snapshot fields, validator grammar, and result contracts are compatibility surfaces. Hosts adopting the durable session supply a valid server-selected strong validator, keep durable retry/conflict policy, and classify snapshot validator values as confidential local metadata. Any future lifecycle-state, snapshot-field, or retention change requires compatibility tests, migration guidance, and a rollback that preserves host durable state. ## Verification -Queue/session state-machine tests, no-op observation regressions, callback-failure isolation, validator grammar tests, concurrency/flush/close regressions, packed ESM/CommonJS/strict-TypeScript consumers, and exact-head coverage/security gates verify the contract. +Queue/session state-machine tests, active/pending/last-saved snapshot ordering tests, no-op observation regressions, callback-failure isolation, validator grammar tests, concurrency/flush/close regressions, packed ESM/CommonJS/strict-TypeScript consumers, and exact-head coverage/security gates verify the contract. Documentation tests must preserve the distinction between the explicit `getSnapshot()` coordination surface and generic diagnostics/telemetry. ## Rollback or supersession -Rollback removes optional lifecycle observation or durable-session convenience while preserving explicit `getSnapshot()`, local queue ordering, and host-owned durable writes. Supersession requires an equally bounded concurrency model, exact validator semantics, migration/rollback, and fresh package-consumer evidence. +Rollback removes optional lifecycle observation or durable-session convenience while preserving explicit `getSnapshot()`, local queue ordering, and host-owned durable writes. Removing or renaming validator snapshot fields requires a documented compatibility migration rather than silently changing the privacy contract. Supersession requires an equally bounded concurrency model, exact validator semantics, migration/rollback, and fresh package-consumer evidence. From 4ad9a2b859a57c8d6c5a0630d5508711aedc4dde Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:20:39 +0900 Subject: [PATCH 084/101] docs(contracts): bind exact release draft inventory and digest gate --- docs/CONTRACTS.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/CONTRACTS.md b/docs/CONTRACTS.md index 30b0e8ba..54ddaef6 100644 --- a/docs/CONTRACTS.md +++ b/docs/CONTRACTS.md @@ -49,7 +49,7 @@ Autosave is a local coordination surface. It provides bounded single-flight orde A server-selected strong validator is the durable concurrency authority. It advances only from a validated successful host result. Conflict, timeout ambiguity, malformed callback output, host failure, promise/reflection failure, or observer failure never fabricates durable success. -Lifecycle observation emits only distinct externally visible document-free states. Construction and no-op operations do not manufacture events. +Lifecycle observation emits only distinct externally visible document-free states. Construction and no-op operations do not manufacture events. The explicit local `getSnapshot()` coordination API may expose bounded active/pending/last-saved strong-validator fields defined by the autosave contract; those values remain confidential local concurrency metadata and are not generic diagnostics or telemetry. Degraded behavior: when host persistence is unavailable or ambiguous, Inkspan preserves local state and explicit blocked/failure evidence rather than inventing a durable save. @@ -108,6 +108,8 @@ 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. + Rollback must preserve readable canonical documents and must not require silently reinterpreting persisted schema semantics. Host-owned migrations, persistence rollback, tenant recovery, and deployment rollback remain host responsibilities unless a future versioned contract explicitly assigns them to Inkspan. ## Contract-to-authority map @@ -121,7 +123,7 @@ Rollback must preserve readable canonical documents and must not require silentl | Office rendering | deterministic bounded JSON→artifact conversion | file destination policy, downstream distribution, tenant authorization | | 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 | package/artifact verification and repository evidence | downstream deployment and operational rollout | +| release evidence | exact three-file draft inventory, package/artifact/digest verification and repository evidence | downstream deployment and operational rollout | ## Related canonical documents @@ -130,7 +132,7 @@ Rollback must preserve readable canonical documents and must not require silentl - `ARCHITECTURE.md` — protected-main implementation architecture. - `docs/UML.md` and `docs/DATA_MODEL.md` — interaction and conceptual data/evidence views. - `docs/THREAT_MODEL.md` — threat analysis and trust boundaries. -- `docs/TEST_STRATEGY.md` — machine evidence required for these contracts. -- `docs/OPERABILITY.md` — failure, recovery, rollback, and incident ownership. +- `docs/TEST_STRATEGY.md` — machine evidence required for these contracts, including the exact release draft inventory/digest gate. +- `docs/OPERABILITY.md` — failure, recovery, rollback, incident ownership, and release draft reconciliation. - `docs/TRACEABILITY.md` — standards, research, and implementation evidence traceability. - `docs/adr/README.md` — detailed architectural decisions. From ecea0aa5e7519ddcc4f6acd8d9e504f9edd91ef5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:21:13 +0900 Subject: [PATCH 085/101] docs(operability): bind exact release inventory and private observability --- docs/OPERABILITY.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/OPERABILITY.md b/docs/OPERABILITY.md index 1232c21d..482bdf0c 100644 --- a/docs/OPERABILITY.md +++ b/docs/OPERABILITY.md @@ -14,13 +14,13 @@ Protected `main` is the shipped implementation authority. Open PRs are not opera Inkspan itself does not expose a network health endpoint. Operational health is proven through exact-head CI and package-consumer evidence, deterministic runtime outcomes, bounded public errors, security scans, package/release verification, and host-observable local state. -Hosts may derive UI or local telemetry from document-free lifecycle snapshots, but must not expose document bodies, revision/entity tags, provider metadata, tenant identifiers, prompts, or model outputs as public metric dimensions or unauthenticated logs. High-cardinality tenant-confidential equality metadata remains local/private unless a host policy explicitly authorizes sharing. +Hosts may derive UI or private local observability from bounded lifecycle/snapshot state, but complete document bodies, revision/entity tags, durable validators, provider metadata, awareness state, tenant identifiers, schema identity, browser evidence, prompts, model outputs, or comparable tenant-confidential/release-sensitive values must never become public high-cardinality metric labels or unauthenticated logs. Any separate sharing is authenticated, purpose-bound, minimum-disclosure, and host-authorized; that separate channel does not redefine public telemetry as safe. ## Autosave operations The local autosave queue is single-flight with bounded pending work. Durable sessions use a host/server-selected strong HTTP entity tag for compare-and-swap. A local SHA-256 document revision is not a durable validator. -Operational states are `idle`, `saving`, `blocked`, `closing`, and `closed`. Blocked conflict or ambiguous failure requires explicit recovery. No-op lifecycle operations do not manufacture synthetic state changes. Observer exceptions are presentation/telemetry failures and must not change persistence ordering. +Operational states are `idle`, `saving`, `blocked`, `closing`, and `closed`. Blocked conflict or ambiguous failure requires explicit recovery. No-op lifecycle operations do not manufacture synthetic state changes. Observer exceptions are presentation/telemetry failures and must not change persistence ordering. The explicit in-process `getSnapshot()` coordination surface may contain bounded active/pending/last-saved validator fields; operators must classify those values as confidential local concurrency metadata rather than generic diagnostics. Host operators should treat: @@ -41,17 +41,18 @@ File publication must follow the documented atomic/non-overwrite behavior. A cal ## Release operations -Release publication occurs only from an exact integrated protected head. Release evidence includes package artifacts, deterministic checksums, CI/security/package/provenance results, required review, zero valid unresolved findings, and repository-policy acceptance. +Release publication occurs only from an exact integrated protected head. Release evidence includes package artifacts, deterministic checksums, CI/security/package/provenance results, required review, zero valid unresolved findings, and repository-policy acceptance. The normative inventory and digest rules are defined by the `docs/CONTRACTS.md` Release and rollback contract. Before publication: -1. build the exact expected artifact inventory; -2. verify local entries and digests; -3. verify any resumed remote draft has exactly the expected uploaded asset names and digests; -4. fail closed on stale/unexpected/incomplete assets rather than deleting them automatically; -5. verify SBOM/provenance/signing or attestation gates where configured; -6. verify package/wheel consumers and supported runtime matrix; -7. publish only after exact-head required review and protection gates pass. +1. build exactly three regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, and `SHA256SUMS`; +2. reject missing, duplicate, non-regular, stale, or unexpected local entries and verify the local digests; +3. 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; +4. require every remote asset state to be uploaded and every GitHub-reported `sha256:` digest to equal the exact transferred local file digest; +5. fail closed on stale/unexpected/incomplete/digest-mismatched assets rather than deleting them automatically to manufacture a clean draft; +6. verify SBOM/provenance/signing or attestation gates where configured; +7. verify package/wheel consumers and the supported runtime matrix; and +8. publish only after exact-head required review and protection gates pass. After publication, verify artifact availability, checksums/provenance, package metadata, install/consumer smoke evidence, and release notes. Rollback of a bad release uses a new reviewed corrective release or repository-supported withdrawal/yank policy; immutable published evidence is not rewritten to pretend the release never existed. @@ -59,7 +60,7 @@ After publication, verify artifact availability, checksums/provenance, package m ### Security input bypass -Stop publication of affected versions, reproduce on exact source, preserve a minimized synthetic regression, classify whether the defect is inside Inkspan or host policy, patch test-first, rerun security/package/release evidence, and follow `SECURITY.md` disclosure handling once it is protected-main authority. Do not publish proof-of-concept customer data. +Stop publication of affected versions, reproduce on exact source, preserve a minimized synthetic regression, classify whether the defect is inside Inkspan or host policy, patch test-first, rerun security/package/release evidence, and follow the protected-main root `SECURITY.md` private-reporting and coordinated-disclosure lifecycle. Do not publish proof-of-concept customer data. ### Data-loss or false durable-success risk From 33e58f4a544437345b2589de90123f8ca34f7f07 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:21:53 +0900 Subject: [PATCH 086/101] docs(test): align coverage and release gates with protected CI --- docs/TEST_STRATEGY.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index d310f528..0e40aefa 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -38,9 +38,9 @@ Verify native control semantics, focus behavior, `aria-pressed`, `aria-keyshortc ## Coverage policy -Owned production code targets exact 100% statement, branch, function, and line coverage where supported by the language/toolchain. Coverage is a structural completeness gate, not proof of semantic correctness. Tests must continue to include realistic domain and adversarial behavior instead of creating vacuous branches merely to satisfy a percentage. +JavaScript/TypeScript owned production code is enforced at exact 100% statements, branches, functions, and lines by the repository Vitest/V8 coverage configuration. Coverage is a structural completeness gate, not proof of semantic correctness. Tests must continue to include realistic domain and adversarial behavior instead of creating vacuous branches merely to satisfy a percentage. -Office Python surfaces additionally require complete public docstrings and branch/statement coverage under the supported Python matrix. JavaScript/TypeScript public declarations and package boundaries require strict consumer compilation. +Office Python uses a distinct language/tool contract. Across every advertised supported Python minor on protected CI, `coverage.py` runs with branch measurement enabled, `coverage report` is required to meet `fail_under = 100`, and `show_missing = true` exposes uncovered statement lines and missing branch destinations/start lines. The Office gate also requires 100% public-docstring completeness through `scripts/check_docstrings.py`. Python has no separate JavaScript-style function/line percentage counters in this repository contract; do not relabel the coverage.py report as four independent metrics. JavaScript/TypeScript public declarations and package boundaries additionally require strict packed-consumer compilation. ## Security corpus @@ -52,7 +52,7 @@ At minimum, maintain regressions for: - autosave stale validators, conflict/failure recovery, ambiguous transport outcomes, duplicate/no-op lifecycle transitions, callback exceptions, queue bounds, flush/close behavior, and durable-validator coherence; - selection/revision races and document movement during asynchronous hashing; - Office formula prefixes, invalid XML characters, malicious strings, path/publication races, invalid worksheet names, invalid freeze panes, cyclic input, pathological nesting, excessive container size, and partial write failure; -- package/release stale draft assets, unexpected local entries, digest mismatch, stale exact-head evidence, mutable provenance inputs, and isolated packed-consumer behavior. +- package/release stale draft assets, unexpected or non-regular local entries, exact three-file inventory violations, incomplete remote uploads, GitHub-vs-local digest mismatch, stale exact-head evidence, mutable provenance inputs, and isolated packed-consumer behavior. ## Concurrency and failure testing @@ -62,7 +62,9 @@ Host persistence transactions, tenant isolation, distributed collaboration autho ## Release acceptance -A release candidate requires the exact integrated protected head to satisfy applicable CI, security, 100% owned production coverage, public-docstring, package-consumer, accessibility, browser differential, Office artifact, SBOM/provenance, reproducibility, unresolved-thread, independent-review, and release-workflow gates. Queued, skipped-required, cancelled, absent, stale-head, predecessor-head, status-only, or synthetic-merge evidence is not accepted as success. +A release candidate requires the exact integrated protected head to satisfy applicable CI, security, JavaScript/TypeScript 100% statement/branch/function/line coverage, Office coverage.py 100% report plus public-docstring completeness, package-consumer, accessibility, browser differential, Office artifact, SBOM/provenance, reproducibility, unresolved-thread, actually required independent-review, and release-workflow gates. Queued, skipped-required, cancelled, absent, stale-head, predecessor-head, status-only, or synthetic-merge evidence is not accepted as success. + +The release workflow must also satisfy the normative `docs/CONTRACTS.md` draft inventory contract: exactly one npm tarball, exactly one Office wheel, and `SHA256SUMS`; no other top-level entry; remote uploaded asset names exactly equal local names; and every GitHub-reported `sha256:` digest equals the exact transferred local file digest. Missing, stale, unexpected, non-regular, incomplete, or digest-mismatched assets are failures, not cleanup opportunities. The 0.6.0 rich-clipboard release line specifically requires the Chromium, Firefox, and WebKit differential gate before publication. Deterministic jsdom coverage remains useful but is not a substitute for browser-engine acceptance. From e5df2e7f8901e8574d001d1fe16c77b823b5f845 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 00:22:44 +0900 Subject: [PATCH 087/101] docs(data): fail closed on public telemetry metadata --- docs/DATA_MODEL.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/DATA_MODEL.md b/docs/DATA_MODEL.md index 2e47e24b..b2aaa0fd 100644 --- a/docs/DATA_MODEL.md +++ b/docs/DATA_MODEL.md @@ -45,7 +45,7 @@ erDiagram - `document_transition`: previous/resulting revision pair plus changed classification. It deliberately omits the document body from ordinary evidence. - `selection_evidence`: ProseMirror structural coordinates bound to one exact revision. It is a local evidence value, not a durable cross-revision anchor. - `autosave_revision`: detached immutable revision evidence accepted by the local single-flight autosave coordinator. -- `autosave_snapshot`: frozen document-free queue/session lifecycle metadata such as idle/saving/blocked/closing/closed and bounded pending state. +- `autosave_snapshot`: frozen document-free queue/session lifecycle metadata such as idle/saving/blocked/closing/closed and bounded pending state. The explicit in-process snapshot may also carry the bounded active/pending/last-saved strong-validator fields defined by the autosave contract; those fields are confidential local concurrency metadata rather than generic telemetry. - `clipboard_policy`: bounded local policy describing the supported semantic rich-paste boundary. It grants no host network or tenant authority. - `conversion_request`: versioned deterministic conversion intent. It identifies the supported source representation, requested target such as Markdown/HTML/DOCX/XLSX/PPTX, explicit output/publication options, and validated render configuration. It is a runtime value, not a durable job record. - `conversion_artifact`: completed deterministic conversion result or artifact identity produced only after validation/build/publication succeeds. A partial/failed output is not a `conversion_artifact` success. @@ -83,7 +83,7 @@ These values may remain ephemeral or release-artifact metadata. Their presence i | `document_transition` | none required; host may store | change evidence | no | content-lineage evidence only | | `selection_evidence` | none required | review/selection capture | no | exact-revision coordinates only | | `autosave_revision` | none required | queued local save evidence | envelope-bearing evidence may be retained boundedly by queue | local save ordering only | -| `autosave_snapshot` | none required | lifecycle observation | no | local machine state only | +| `autosave_snapshot` | none required | lifecycle observation/coordination | no | local machine state only; validator fields remain confidential metadata | | `durable_validator` | host | durable version | no | host concurrency evidence, not authorization | | `collaboration_document` | host/provider | collaborative room/document | yes, as Yjs state | host/provider authority | | `awareness_state` | host/provider | ephemeral presence | not normally document body | no authorization | @@ -112,14 +112,14 @@ The current Inkspan runtime does not create a tenant database, but products embe ## Privacy and minimum-disclosure rules -Ordinary lifecycle/selection/transition/schema-identity evidence should remain document-free. Revision/entity tags, provider metadata, awareness state, schema identity, browser evidence and host identifiers can still be tenant-confidential or release-sensitive metadata and must not become public high-cardinality metric labels or unauthenticated logs without an explicit policy. Complete document envelopes, Yjs state, conversion inputs/artifacts, prompts/model outputs, credentials, and host authorization claims follow the host's purpose, encryption, retention, and access policy. +Ordinary lifecycle/selection/transition/schema-identity evidence should remain document-free. Revision/entity tags, durable validators, provider metadata, awareness state, schema identity, browser evidence, and host identifiers can still be tenant-confidential or release-sensitive metadata and **must never** become public high-cardinality metric labels or unauthenticated logs. Any separate sharing is limited to authenticated, purpose-bound, minimum-disclosure channels under host policy; such a channel does not create an exception for public metrics or unauthenticated logging. Complete document envelopes, Yjs state, conversion inputs/artifacts, prompts/model outputs, credentials, and host authorization claims follow the host's purpose, encryption, retention, and access policy. ## Persistence non-applicability and future change No Inkspan-owned relational schema is required by the current architecture, so no physical database ERD or migration set is invented here merely to satisfy documentation completeness. Planned identity-routing and browser-assurance values are logical API/evidence objects, not database tables. If Inkspan later introduces durable persistence, that is a material architecture change requiring: 1. an Accepted ADR defining why persistence moved into Inkspan; -2. a physical ERD with descriptive multiword `snake_case` object names; +2. a physical database ERD with descriptive multiword `snake_case` object names; 3. tenant, temporal, provenance, retention, encryption, authorization, and audit semantics; 4. migrations, backup/restore and rollback/recovery design; and 5. a revised threat model, test strategy, operability runbook, and acquisition evidence package. From f8788a4c75ab7bab3903d211cfce604fb36a3625 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:07:54 +0900 Subject: [PATCH 088/101] test(docs): bind merged autosave lifecycle status --- src/canonicalProductDocumentation.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index f01e5c4e..daeb989d 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -97,6 +97,20 @@ describe('canonical product documentation graph', () => { expect(productDefinition).toContain('not shipped claims'); }); + it('does not leave merged autosave lifecycle observation classified as active-PR work', () => { + const prd = repositoryFile('docs/PRD.md'); + const trd = repositoryFile('docs/TRD.md'); + const fitness = repositoryFile('docs/DOCUMENTATION_FITNESS.md'); + const currentScope = prd.slice(prd.indexOf('## Current, proposed, and planned scope')); + + expect(currentScope).toContain('Lifecycle observation is implemented on protected `main`'); + expect(currentScope).not.toMatch(/open development lines include[^.]*lifecycle observation/u); + expect(trd).toContain('Autosave lifecycle observation is implemented on protected `main`'); + expect(trd).not.toContain('open clipboard, autosave observation'); + expect(fitness).toContain('Autosave lifecycle observation'); + expect(fitness).toMatch(/Autosave lifecycle observation[^\n]*implemented_on_protected_main/u); + }); + it('records host ownership and deterministic Inkspan authority consistently', () => { const prd = repositoryFile('docs/PRD.md'); const trd = repositoryFile('docs/TRD.md'); From 0d56877b21cff0db9719ec0120e484b0556f095b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:08:22 +0900 Subject: [PATCH 089/101] docs(prd): mark autosave lifecycle observation protected --- docs/PRD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 38dd0116..10196a0b 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -4,7 +4,7 @@ Status: Proposed canonical baseline ## Product definition -Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. This canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling, revision-scoped selection/transition evidence, SSR/native-form integration, and lifecycle observation; they are target requirements, not shipped claims, until protected integration. Across current and proposed scope, Inkspan keeps host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. +Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation is now implemented on protected `main`; this canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling, revision-scoped selection/transition evidence, and SSR/native-form integration, which remain target requirements rather than shipped claims until protected integration. Across current and proposed scope, Inkspan keeps host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. The product promise is: **author, convert, collaborate, and prove document changes without hiding authority inside the editor.** @@ -127,4 +127,4 @@ 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. -The root security disclosure lifecycle is implemented on protected `main`. Current open development lines include richer browser-verified clipboard assurance, lifecycle observation, document-transition/revision evidence, SSR/native-form integration, accessibility metadata, and canonical documentation reconciliation. Their detail is useful design evidence but remains Proposed until merged. A future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. +The root security disclosure lifecycle is implemented on protected `main`. Lifecycle observation is implemented on protected `main`. Current open development lines include richer browser-verified clipboard assurance, document-transition/revision evidence, SSR/native-form integration, accessibility metadata, and canonical documentation reconciliation. Their detail is useful design evidence but remains Proposed until merged. A future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. From 3c880008fffbaae72c15b8674dd1554d7ad78917 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:08:44 +0900 Subject: [PATCH 090/101] docs(trd): mark autosave lifecycle observation protected --- docs/TRD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/TRD.md b/docs/TRD.md index 3fae38e0..5dbf906c 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -46,7 +46,7 @@ States are `idle`, `saving`, `blocked`, `closing`, and `closed`, with explicit b Durable sessions carry a host/server-selected strong HTTP entity tag. Successful host callbacks may advance the durable validator only from a validated replacement strong tag. Conflict, malformed result, callback failure, hostile reflection, promise-assimilation failure, timeout/network ambiguity, or explicit host failure never silently advances it. -Lifecycle observation is optional and bounded to one construction-time callback. Construction emits nothing. Only distinct externally visible document-free snapshots are emitted. A method call producing no visible lifecycle transition, including a no-op `resume()`, emits nothing. Observer exceptions are isolated from queue ordering, save outcomes, recovery, and durable-validator handoff. +Autosave lifecycle observation is implemented on protected `main`. Observation is optional and bounded to one construction-time callback. Construction emits nothing. Only distinct externally visible document-free snapshots are emitted. A method call producing no visible lifecycle transition, including a no-op `resume()`, emits nothing. Observer exceptions are isolated from queue ordering, save outcomes, recovery, and durable-validator handoff. ## Provider-neutral collaboration @@ -105,4 +105,4 @@ Queued, cancelled, skipped-required, absent, stale-head, predecessor-head, statu ## Implemented versus proposed -Protected `main` is the sole implemented baseline. The security disclosure lifecycle is implemented on protected `main`. Requirements describing open clipboard, autosave observation, transition/selection evidence, SSR/native-form, or accessibility PRs remain Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. +Protected `main` is the sole implemented baseline. The security disclosure lifecycle and autosave lifecycle observation are implemented on protected `main`. Requirements describing open clipboard, transition/selection evidence, SSR/native-form, or accessibility PRs remain Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. From 5f926592c4d1aa43503029b89c31cac71f213724 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:09:26 +0900 Subject: [PATCH 091/101] docs(fitness): reconcile protected autosave lifecycle --- docs/DOCUMENTATION_FITNESS.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index b76b74e8..15b9971d 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -43,6 +43,7 @@ Document fitness and implementation maturity are independent. A `present_current | DATA_MODEL / ERD | `docs/DATA_MODEL.md` | `present_current` | Current logical evidence/domain model; host persistence remains outside Inkspan | The model distinguishes document/evidence/conversion/release values from host-owned entities. | | physical relational ERD | none by design | `not_applicable` | `out_of_scope` while Inkspan owns no application database | No fake database is invented merely to satisfy an ERD checklist; a physical ERD becomes mandatory if persistence authority moves into Inkspan. | | SECURITY disclosure policy | root `SECURITY.md` plus ADR 0017 | `present_current` | `implemented_on_protected_main`; the root policy is protected authority and ADR 0017 records its durable architecture/process decision | Private reporting, evidence minimization, supported release-line binding, ownership limits, coordinated disclosure, and explicit no-SLA/no-certification claim boundaries are reconstructable. | +| Autosave lifecycle observation | PRD, TRD, `docs/document-autosave.md`, lifecycle doctoring and protected autosave package/session source | `present_current` | `implemented_on_protected_main`; protected main exposes the bounded construction-time observer contract | Buyers can reconstruct saving/blocked/recovery/idle/shutdown observation, document-free snapshots, observer-failure isolation, and durable-validator coherence without treating it as an active-PR promise. | | THREAT_MODEL | `docs/THREAT_MODEL.md` | `present_current` | Covers current and explicitly proposed trust boundaries | Clipboard, Office, SSR/form, Yjs, model, host-authority and supply-chain threats are reconstructable. | | TEST_STRATEGY | `docs/TEST_STRATEGY.md` | `present_current` | Current deterministic evidence plus `planned` cross-engine acceptance where dependency order requires it | Test authority and claim limits are explicit rather than inferred from CI badges. | | OPERABILITY | `docs/OPERABILITY.md` | `present_current` | Current local/product responsibilities plus host-owned recovery boundaries | Conflict, collaboration, conversion and release recovery/rollback ownership are explicit. | @@ -62,6 +63,7 @@ The canonical graph must retain durable product decisions from the project conve - bundled local/offline font licensing and air-gapped asset behavior; - deterministic email/document conversion boundaries and independently reusable Office rendering; - provider-neutral collaboration with host-owned Yjs provider, room, persistence and awareness authority; +- bounded protected-main autosave lifecycle observation with document-free distinct snapshots and observer-failure isolation; - naruon `compose` / `ui.panel` modular integration without making naruon a standalone runtime dependency; - model assistance as untrusted proposed content rather than conversion or persistence authority; - accessibility, keyboard, print/export and document-fidelity evidence boundaries; @@ -81,12 +83,12 @@ The documentation pack itself is substantially complete for acquisition review, 1. Issue #74 remains `planned`: the identity-only migration-routing API must still be implemented test-first while the current parser remains strict. Its architectural decision is now present rather than hidden in issue prose. 2. Issue #66 remains `planned` behind PR #65: the dependency-locked Chromium/Firefox/WebKit differential suite must still be implemented before the rich-clipboard release line. Its release-assurance decision is now present rather than hidden in issue prose. -3. Active feature branches for autosave observation, revision evidence, SSR/native forms, accessibility, and SafeClipboard remain `implemented_on_active_pr` until protected integration. -4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge; the already integrated root `SECURITY.md` is protected authority even while this branch is temporarily behind it. +3. Active feature branches for revision evidence, SSR/native forms, accessibility, and SafeClipboard remain `implemented_on_active_pr` until protected integration. Autosave lifecycle observation is no longer in this set because it is integrated on protected `main`. +4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge; protected security disclosure and autosave lifecycle behavior remain authority even while this branch is temporarily behind them. 5. Documentation becoming mergeable or protected-merged is not a reason for the commercial loop to stop; the next safe product, release, security, accessibility or interoperability lane must continue. ## Sufficiency decision -For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. The security disclosure lifecycle is `implemented_on_protected_main` and represented by root `SECURITY.md` plus Proposed ADR 0017. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. +For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Autosave lifecycle observation and the security disclosure lifecycle are `implemented_on_protected_main`. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. No material product architecture decision identified by this review remains only in chat or issue prose. Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph is reconciled with the latest protected source generation and passes normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. From 331eb1755bf897bc256b54b6ca308b6ed5703d9f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:51:52 +0900 Subject: [PATCH 092/101] docs(fitness): reconcile protected SSR and accessibility integration --- docs/DOCUMENTATION_FITNESS.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index 15b9971d..c87d3d0d 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -35,7 +35,7 @@ Document fitness and implementation maturity are independent. A `present_current | Family | Canonical artifact | Documentation fitness | Implementation / authority interpretation | Acquisition conclusion | | --- | --- | --- | --- | --- | | PRD | `docs/PRD.md` | `present_current` | Mix of `implemented_on_protected_main`, `implemented_on_active_pr`, and `planned`, explicitly labeled | Product promise, users, JTBD, non-goals, security, accessibility and release acceptance are reconstructable. | -| TRD | `docs/TRD.md` | `present_current` | Same mixed maturity discipline; Protected `main` remains runtime authority | Technical invariants, failure semantics, package boundaries and release evidence are reconstructable. | +| TRD | `docs/TRD.md` | `present_current` | Same mixed maturity discipline; protected `main` remains runtime authority | Technical invariants, failure semantics, package boundaries and release evidence are reconstructable. | | ARCHITECTURE | `ARCHITECTURE.md` | `present_current` | `implemented_on_protected_main` for the bounded standalone/modular architecture | Host-vs-Inkspan authority and modular CWL composition are explicit. | | Public/API/schema/plugin contracts | `docs/CONTRACTS.md` | `present_current` | Protected-main contracts plus explicitly proposed extensions | Integration authority and degraded behavior are not hidden in implementation details. | | ADR | `docs/adr/README.md` and detailed ADRs | `present_current` | Decisions distinguish current, proposed and future work; ADR 0017 records the protected security-disclosure lifecycle without duplicating its root policy | Alternatives, consequences, recovery, migration, verification and supersession are reviewable. | @@ -44,11 +44,15 @@ Document fitness and implementation maturity are independent. A `present_current | physical relational ERD | none by design | `not_applicable` | `out_of_scope` while Inkspan owns no application database | No fake database is invented merely to satisfy an ERD checklist; a physical ERD becomes mandatory if persistence authority moves into Inkspan. | | SECURITY disclosure policy | root `SECURITY.md` plus ADR 0017 | `present_current` | `implemented_on_protected_main`; the root policy is protected authority and ADR 0017 records its durable architecture/process decision | Private reporting, evidence minimization, supported release-line binding, ownership limits, coordinated disclosure, and explicit no-SLA/no-certification claim boundaries are reconstructable. | | Autosave lifecycle observation | PRD, TRD, `docs/document-autosave.md`, lifecycle doctoring and protected autosave package/session source | `present_current` | `implemented_on_protected_main`; protected main exposes the bounded construction-time observer contract | Buyers can reconstruct saving/blocked/recovery/idle/shutdown observation, document-free snapshots, observer-failure isolation, and durable-validator coherence without treating it as an active-PR promise. | +| SSR/native-form serialization | PRD, TRD, `docs/server-rendering.md`, SSR doctoring and protected editor/form source | `present_current` | `implemented_on_protected_main`; protected main includes the explicit server-value handoff and synchronous hydrated mirror | Buyers can reconstruct opt-in server serialization, hydration continuity, client-controlled submission semantics, reset behavior and host-owned auth/CSRF/persistence boundaries. | +| Toolbar shortcut accessibility metadata | PRD/TRD accessibility requirements, accessibility guide/doctoring and protected toolbar source | `present_current` | `implemented_on_protected_main`; shipped bold/italic/link/undo/redo shortcuts expose truthful `aria-keyshortcuts` metadata | Accessibility metadata is tied to actual repository-level keyboard behavior rather than extension-local assumptions. | +| Revision-scoped selection evidence | selection lifecycle guide, doctoring, public handle/type contract and current replacement PR | `present_current` | `implemented_on_active_pr`; current-main replacement work is not shipped until protected integration | Atomic selection+revision evidence, privacy minimization and host-owned re-anchoring are reconstructable without promoting the active PR. | +| Document-transition evidence | transition doctoring/public contract and PR #68 | `present_current` | `implemented_on_active_pr`; the framework-independent transition-evidence branch is not protected authority yet | Previous/resulting revision lineage and privacy/provenance boundaries remain explicit while integration is pending. | | THREAT_MODEL | `docs/THREAT_MODEL.md` | `present_current` | Covers current and explicitly proposed trust boundaries | Clipboard, Office, SSR/form, Yjs, model, host-authority and supply-chain threats are reconstructable. | | TEST_STRATEGY | `docs/TEST_STRATEGY.md` | `present_current` | Current deterministic evidence plus `planned` cross-engine acceptance where dependency order requires it | Test authority and claim limits are explicit rather than inferred from CI badges. | | OPERABILITY | `docs/OPERABILITY.md` | `present_current` | Current local/product responsibilities plus host-owned recovery boundaries | Conflict, collaboration, conversion and release recovery/rollback ownership are explicit. | | Release / rollback / provenance | TRD, OPERABILITY and release ADRs | `present_current` | Mix of `implemented_on_protected_main` and active hardening | Exact-source release authority, stale-evidence rejection and rollback are reconstructable. | -| Envelope schema identity / migration routing | ADR 0015, PRD, TRD, DATA_MODEL and Issue #74 | `present_current` | Identity-only routing capability is `planned`; strict current-schema parsing and host migration ownership remain authoritative | The architecture now distinguishes bounded schema identification from host-owned migration execution without calling the planned API shipped. | +| Envelope schema identity / migration routing | ADR 0015, PRD, TRD, DATA_MODEL and Issue #74 | `present_current` | Identity-only routing capability is `planned`; strict current-schema parsing and host migration ownership remain authoritative | The architecture distinguishes bounded schema identification from host-owned migration execution without calling the planned API shipped. | | Cross-engine browser-semantic release assurance | ADR 0016, UML, TEST_STRATEGY, TRACEABILITY and Issue #66 | `present_current` | Differential Chromium/Firefox/WebKit release gate is `planned` behind PR #65 | Browser-realistic security assurance is a durable release decision even though its implementation remains dependency-ordered future work. | | TRACEABILITY | `docs/TRACEABILITY.md` | `present_current` | Links standards/research/requirements to decisions and evidence with scoped claims | Acquisition reviewers can distinguish evidence from aspiration. | | Contributor/agent authority | `AGENTS.md`, `CLAUDE.md`, `docs/README.md` | `present_current` | Protected-main-first decision discipline | Agents are directed back to the same canonical graph rather than parallel private memory. | @@ -64,6 +68,9 @@ The canonical graph must retain durable product decisions from the project conve - deterministic email/document conversion boundaries and independently reusable Office rendering; - provider-neutral collaboration with host-owned Yjs provider, room, persistence and awareness authority; - bounded protected-main autosave lifecycle observation with document-free distinct snapshots and observer-failure isolation; +- protected-main SSR/native-form serialization with opt-in document disclosure, controlled hydration handoff, synchronous native-field mirroring, and host-owned acceptance controls; +- protected-main toolbar shortcut metadata that reflects the actual cross-platform bold, italic, link, undo and redo bindings; +- revision-scoped selection and document-transition evidence as active-PR capabilities rather than protected-main claims; - naruon `compose` / `ui.panel` modular integration without making naruon a standalone runtime dependency; - model assistance as untrusted proposed content rather than conversion or persistence authority; - accessibility, keyboard, print/export and document-fidelity evidence boundaries; @@ -75,7 +82,7 @@ The canonical graph must retain durable product decisions from the project conve Autonomous commercial-maintenance scheduling and the no-early-stop execution discipline are **control-plane governance, not a shipped Inkspan product capability**. The external scheduler is the execution authority for cadence and continuation; repository guidance records writer leases, work-conserving queue behavior, lane-local waiting, evidence hierarchy and protected-main authority without pretending the automation prompt is a runtime API or architectural feature. -Where an older conversation, PR body, or plan conflicts with Protected `main`, it is historical rather than canonical. Where a requirement is only on an active PR, this documentation may describe it as `implemented_on_active_pr` but never as shipped. +Where an older conversation, PR body, or plan conflicts with protected `main`, it is historical rather than canonical. Where a requirement is only on an active PR, this documentation may describe it as `implemented_on_active_pr` but never as shipped. ## Remaining documentation and product gaps @@ -83,12 +90,12 @@ The documentation pack itself is substantially complete for acquisition review, 1. Issue #74 remains `planned`: the identity-only migration-routing API must still be implemented test-first while the current parser remains strict. Its architectural decision is now present rather than hidden in issue prose. 2. Issue #66 remains `planned` behind PR #65: the dependency-locked Chromium/Firefox/WebKit differential suite must still be implemented before the rich-clipboard release line. Its release-assurance decision is now present rather than hidden in issue prose. -3. Active feature branches for revision evidence, SSR/native forms, accessibility, and SafeClipboard remain `implemented_on_active_pr` until protected integration. Autosave lifecycle observation is no longer in this set because it is integrated on protected `main`. -4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge; protected security disclosure and autosave lifecycle behavior remain authority even while this branch is temporarily behind them. +3. Document-transition evidence (PR #68), revision-scoped selection evidence (current replacement lane), and SafeClipboard (PR #65) remain `implemented_on_active_pr` until protected integration. Autosave lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, and SSR/native-form serialization are now `implemented_on_protected_main` and must not be described as active-only work. +4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge. At this review point protected main is at least `268ef8ec25a82edff863b4deace7d431333cd3a6`; later source movement must be refetched rather than hard-coded as timeless architecture. 5. Documentation becoming mergeable or protected-merged is not a reason for the commercial loop to stop; the next safe product, release, security, accessibility or interoperability lane must continue. ## Sufficiency decision -For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Autosave lifecycle observation and the security disclosure lifecycle are `implemented_on_protected_main`. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. +For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Autosave lifecycle observation, the security disclosure lifecycle, toolbar shortcut accessibility metadata, and SSR/native-form serialization are `implemented_on_protected_main`. Revision-scoped selection evidence, document-transition evidence, and SafeClipboard remain active-PR work. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. No material product architecture decision identified by this review remains only in chat or issue prose. Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph is reconciled with the latest protected source generation and passes normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. From 94daef6f770e61f85225dae64d38caa479689d94 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:52:32 +0900 Subject: [PATCH 093/101] docs(prd): reconcile protected SSR and accessibility capabilities --- docs/PRD.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 10196a0b..71b1e57d 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -4,7 +4,7 @@ Status: Proposed canonical baseline ## Product definition -Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation is now implemented on protected `main`; this canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling, revision-scoped selection/transition evidence, and SSR/native-form integration, which remain target requirements rather than shipped claims until protected integration. Across current and proposed scope, Inkspan keeps host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. +Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, and SSR/native-form serialization are implemented on protected `main`; this canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling and revision-scoped selection/transition evidence, which remain target requirements rather than shipped claims until protected integration. Across current and proposed scope, Inkspan keeps host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. The product promise is: **author, convert, collaborate, and prove document changes without hiding authority inside the editor.** @@ -57,6 +57,7 @@ The product promise is: **author, convert, collaborate, and prove document chang - Server rendering never creates a browser editor view. - Optional native-form serialization survives SSR/hydration and remains synchronized once the editor is authoritative. +- Controlled `value` precedes `defaultValue` for the explicitly configured server-rendered field, and the native value is restored from the editor after document-changing transactions and native reset processing. - Hidden/native field values are client-controlled data and never replace host authentication, authorization, CSRF controls, request validation, tenant isolation, or durable concurrency. ### Collaboration @@ -80,7 +81,8 @@ The product promise is: **author, convert, collaborate, and prove document chang ### Accessibility, print, and export -- Native controls, focus behavior, keyboard parity, shortcut metadata, non-color status semantics, and host-facing lifecycle state support WCAG-oriented embedding. +- Native controls, focus behavior, keyboard parity, truthful `aria-keyshortcuts` metadata, non-color status semantics, and host-facing lifecycle state support WCAG-oriented embedding. +- Toolbar shortcut metadata must reflect repository-level shipped behavior, including host/editor bindings such as link editing, rather than only extension-local defaults. - Application-visible saving/conflict/recovery messages must be derivable from programmatic state without Inkspan prescribing untranslated user-facing copy. - Export/print surfaces must not rely on color alone or inaccessible interaction-only state where the corresponding product surface exists. @@ -127,4 +129,4 @@ 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. -The root security disclosure lifecycle is implemented on protected `main`. Lifecycle observation is implemented on protected `main`. Current open development lines include richer browser-verified clipboard assurance, document-transition/revision evidence, SSR/native-form integration, accessibility metadata, and canonical documentation reconciliation. Their detail is useful design evidence but remains Proposed until merged. A future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. +The root security disclosure lifecycle, lifecycle observation, toolbar shortcut accessibility metadata, and SSR/native-form serialization are implemented on protected `main`. Current open development lines include SafeClipboard, document-transition evidence, revision-scoped selection evidence, and canonical documentation reconciliation. Their detail is useful design evidence but remains Proposed until merged. Cross-engine browser assurance remains planned behind SafeClipboard, and a future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. From cf2ab64b7278c45b606ce119f60bb9782ba69e73 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 01:53:06 +0900 Subject: [PATCH 094/101] docs(trd): reconcile protected SSR and accessibility capabilities --- docs/TRD.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/TRD.md b/docs/TRD.md index 5dbf906c..54a13f4b 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -32,14 +32,16 @@ Where browser fragment parsing or serialization can change security semantics, a ## SSR and native forms -Server rendering must not instantiate an editor view. When a native field is explicitly enabled, SSR/hydration serializes the selected controlled Markdown/HTML value as escaped client-controlled input. Once the editor is authoritative, document transactions synchronously mirror the configured serialization into the form field. +SSR/native-form serialization is implemented on protected `main`. Server rendering must not instantiate an editor view. When a native field is explicitly enabled, SSR/hydration serializes the selected controlled Markdown/HTML value as escaped client-controlled input. Controlled `value` precedes `defaultValue` for that field. Before TipTap initializes, prop updates remain authoritative; once the editor is authoritative, document transactions synchronously mirror the configured serialization into the form field, and native reset processing restores the live serialized value when the host does not reset the editor. -The hidden/native field is never authentication, authorization, CSRF protection, tenant identity, signature, integrity proof, or durable-write evidence. Hosts independently validate and authorize submissions. +The hidden/native field is never authentication, authorization, CSRF protection, tenant identity, signature, integrity proof, or durable-write evidence. Hosts independently validate and authorize submissions. Collaborative Yjs content remains absent from the server shell until the host-owned client collaboration lifecycle is established. ## Revision-scoped evidence Selection evidence captures structural coordinates and canonical document state from the same immutable editor snapshot before asynchronous hashing. Transition evidence validates previous and resulting envelopes before sequential revision derivation. Ordinary evidence contains revision/coordinate/change metadata rather than document bodies and does not synthesize actor, tenant, time, model identity, signature, authorization, transport result, or durable-persistence claims. +Selection and transition evidence remain active-PR capabilities until protected integration; these target requirements do not promote those branches to shipped runtime behavior. + ## Autosave state machine and durable concurrency States are `idle`, `saving`, `blocked`, `closing`, and `closed`, with explicit blocked reasons. The local queue remains single-flight and retains bounded active/pending work and bounded flush waiters. Evidence supplied to a callback is immutable and validated before scheduling. @@ -89,7 +91,7 @@ Cancellation, retry/offline policy, network timeout budgets, durable reconciliat ## Accessibility and interaction semantics -Shipped keyboard behavior, focus behavior, native controls, `aria-pressed`, `aria-keyshortcuts`, programmatic save/conflict state, and visible shortcut documentation must agree. Status must not depend on color alone. Inkspan exposes machine state sufficient for host WCAG-oriented messaging while leaving localization and application-specific live-region policy to the host. +Toolbar shortcut metadata is implemented on protected `main`. Shipped keyboard behavior, focus behavior, native controls, `aria-pressed`, `aria-keyshortcuts`, programmatic save/conflict state, and visible shortcut documentation must agree. Repository-level keyboard behavior outranks extension-local defaults when determining metadata. Status must not depend on color alone. Inkspan exposes machine state sufficient for host WCAG-oriented messaging while leaving localization and application-specific live-region policy to the host. ## Packaging, compatibility, and release evidence @@ -101,8 +103,8 @@ Queued, cancelled, skipped-required, absent, stale-head, predecessor-head, statu ## Security, privacy, and operability dependencies -`SECURITY.md`, `docs/THREAT_MODEL.md`, `docs/TEST_STRATEGY.md`, `docs/OPERABILITY.md`, `docs/TRACEABILITY.md`, and the detailed ADR corpus are part of this technical contract. Root `SECURITY.md` is now `implemented_on_protected_main` and is the normative private vulnerability-reporting/coordinated-disclosure policy. ADR 0017 records the durable decision, ownership boundary, claim limits, and recovery/supersession semantics without duplicating the policy text. +`SECURITY.md`, `docs/THREAT_MODEL.md`, `docs/TEST_STRATEGY.md`, `docs/OPERABILITY.md`, `docs/TRACEABILITY.md`, and the detailed ADR corpus are part of this technical contract. Root `SECURITY.md` is `implemented_on_protected_main` and is the normative private vulnerability-reporting/coordinated-disclosure policy. ADR 0017 records the durable decision, ownership boundary, claim limits, and recovery/supersession semantics without duplicating the policy text. ## Implemented versus proposed -Protected `main` is the sole implemented baseline. The security disclosure lifecycle and autosave lifecycle observation are implemented on protected `main`. Requirements describing open clipboard, transition/selection evidence, SSR/native-form, or accessibility PRs remain Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. +Protected `main` is the sole implemented baseline. The security disclosure lifecycle, autosave lifecycle observation, toolbar shortcut accessibility metadata, and SSR/native-form serialization are implemented on protected `main`. Requirements describing SafeClipboard and transition/selection evidence remain Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. From 1bf49f8f15dcbbb3b801103bc8217d4b9bb4c3e8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 02:36:14 +0900 Subject: [PATCH 095/101] test(docs): harden canonical authority contracts --- src/canonicalProductDocumentation.test.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/canonicalProductDocumentation.test.ts b/src/canonicalProductDocumentation.test.ts index daeb989d..c15e2ef9 100644 --- a/src/canonicalProductDocumentation.test.ts +++ b/src/canonicalProductDocumentation.test.ts @@ -119,8 +119,11 @@ describe('canonical product documentation graph', () => { const operability = repositoryFile('docs/OPERABILITY.md'); for (const document of [prd, trd, contracts, threatModel, operability]) { - expect(document).toContain('host'); - expect(document).toMatch(/transport|authorization|tenant|persistence/i); + expect(document).toMatch(/host[^.]*transport/i); + expect(document).toMatch(/host[^.]*authentication/i); + expect(document).toMatch(/host[^.]*authorization/i); + expect(document).toMatch(/host[^.]*tenant(?: isolation|cy)/i); + expect(document).toMatch(/host[^.]*durable persistence|host[^.]*persistence/i); } expect(prd).toContain('deterministic'); expect(trd).toContain('Protected `main`'); @@ -128,7 +131,7 @@ describe('canonical product documentation graph', () => { expect(operability).toContain('rollback'); }); - it('preserves the durable product decisions from the canonical conversation', () => { + it('preserves durable product decisions from the canonical documentation graph', () => { const prd = repositoryFile('docs/PRD.md'); const trd = repositoryFile('docs/TRD.md'); const contracts = repositoryFile('docs/CONTRACTS.md'); @@ -154,6 +157,7 @@ describe('canonical product documentation graph', () => { for (const marker of ['Office', 'naruon', 'Yjs', 'file publication']) { expect(uml).toContain(marker); } + expect(uml).toContain('CI-only; not runtime'); for (const marker of [ 'conversion_request', 'conversion_artifact', @@ -246,8 +250,17 @@ describe('canonical product documentation graph', () => { expect(notice).toContain(marker); } for (const stylesheet of [fullFonts, latinFonts]) { - expect(stylesheet).toContain("url('./files/"); - expect(stylesheet).not.toMatch(/https?:\/\//u); + const fontUrls = [ + ...stylesheet.matchAll( + /url\(\s*(?:'([^']*)'|"([^"]*)"|([^'")\s]+))\s*\)/gu, + ), + ].map(([, singleQuoted, doubleQuoted, unquoted]) => + singleQuoted ?? doubleQuoted ?? unquoted, + ); + expect(fontUrls.length).toBeGreaterThan(0); + for (const url of fontUrls) { + expect(url).toMatch(/^\.\/files\//u); + } } }); From 68e662512b5739ca0580bb441608ae9fdda17a4d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 02:38:26 +0900 Subject: [PATCH 096/101] docs(uml): mark control plane as non-runtime --- docs/UML.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UML.md b/docs/UML.md index be12bc84..fa6c3af5 100644 --- a/docs/UML.md +++ b/docs/UML.md @@ -33,7 +33,7 @@ flowchart LR CollaborationAdapter <--> HostProvider AutosaveCore --> HostStore HostApp --> ModelGateway - ControlPlane -. CI security review provenance release policy .-> EditorCore + ControlPlane -. CI-only; not runtime: security review provenance release policy .-> EditorCore ``` The host owns transport, authentication, authorization, tenant isolation, persistence, credentials, provider lifecycle, retention, deployment, durable audit, and model-use policy. Inkspan owns deterministic local editor/conversion/evidence behavior only. From 82df41fae752e4113ef96cce8ad69241e5af5965 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 02:48:24 +0900 Subject: [PATCH 097/101] docs(product): reconcile merged evidence capabilities --- docs/PRD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 71b1e57d..b983e498 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -4,7 +4,7 @@ Status: Proposed canonical baseline ## Product definition -Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, and SSR/native-form serialization are implemented on protected `main`; this canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling and revision-scoped selection/transition evidence, which remain target requirements rather than shipped claims until protected integration. Across current and proposed scope, Inkspan keeps host transport, identity, authorization, tenancy, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. +Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are implemented on protected `main`; this canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling, which remains a target requirement rather than a shipped claim until protected integration. Across current and proposed scope, Inkspan keeps host transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. The product promise is: **author, convert, collaborate, and prove document changes without hiding authority inside the editor.** @@ -129,4 +129,4 @@ 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. -The root security disclosure lifecycle, lifecycle observation, toolbar shortcut accessibility metadata, and SSR/native-form serialization are implemented on protected `main`. Current open development lines include SafeClipboard, document-transition evidence, revision-scoped selection evidence, and canonical documentation reconciliation. Their detail is useful design evidence but remains Proposed until merged. Cross-engine browser assurance remains planned behind SafeClipboard, and a future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. +The root security disclosure lifecycle, lifecycle observation, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are implemented on protected `main`. Current open development lines include SafeClipboard and canonical documentation reconciliation. Cross-engine browser assurance remains planned behind SafeClipboard, and a future envelope-identity migration-routing API is tracked separately and must preserve host migration ownership. From def86abd4dff410a55237e30d843193b18298461 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 02:49:30 +0900 Subject: [PATCH 098/101] docs(technical): reconcile merged evidence capabilities --- docs/TRD.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/TRD.md b/docs/TRD.md index 54a13f4b..d3ab19bb 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -40,7 +40,7 @@ The hidden/native field is never authentication, authorization, CSRF protection, Selection evidence captures structural coordinates and canonical document state from the same immutable editor snapshot before asynchronous hashing. Transition evidence validates previous and resulting envelopes before sequential revision derivation. Ordinary evidence contains revision/coordinate/change metadata rather than document bodies and does not synthesize actor, tenant, time, model identity, signature, authorization, transport result, or durable-persistence claims. -Selection and transition evidence remain active-PR capabilities until protected integration; these target requirements do not promote those branches to shipped runtime behavior. +Selection and transition evidence are implemented on protected `main`; their local equality/lineage claims remain intentionally narrower than host-owned authorization, occurrence provenance, durable audit, re-anchoring, and persistence authority. ## Autosave state machine and durable concurrency @@ -95,7 +95,7 @@ Toolbar shortcut metadata is implemented on protected `main`. Shipped keyboard b ## Packaging, compatibility, and release evidence -The root package and framework-independent subpaths are verified from packed artifacts under ESM, CommonJS, and strict TypeScript consumers. Office Python surfaces are verified under the documented supported Python matrix, exact production statement/branch coverage, complete public docstrings, built wheel/package inspection, and license/dependency consistency. +The root package and framework-independent subpaths are verified from packed artifacts under ESM, CommonJS, and strict TypeScript consumers. Office Python surfaces are verified under the documented supported Python matrix, exact production statement/branch/function/line coverage, complete public docstrings, built wheel/package inspection, and license/dependency consistency. Release publication verifies one exact integrated protected source head, expected artifact inventory and digests, package/runtime compatibility, security/coverage/accessibility/document-fidelity gates, SBOM/provenance/reproducibility where configured, zero valid unresolved findings, formal review/branch-protection requirements, and post-publication artifact smoke evidence. @@ -107,4 +107,4 @@ Queued, cancelled, skipped-required, absent, stale-head, predecessor-head, statu ## Implemented versus proposed -Protected `main` is the sole implemented baseline. The security disclosure lifecycle, autosave lifecycle observation, toolbar shortcut accessibility metadata, and SSR/native-form serialization are implemented on protected `main`. Requirements describing SafeClipboard and transition/selection evidence remain Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. +Protected `main` is the sole implemented baseline. The security disclosure lifecycle, autosave lifecycle observation, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are implemented on protected `main`. SafeClipboard remains Proposed until merged; migration routing and cross-engine browser assurance remain planned according to their dependency order. Canonical docs distinguish target architecture from shipped behavior and must be updated when the protected implementation changes. From 86d8d178a860b1aaf13877695a6adbd7441fe617 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 02:50:58 +0900 Subject: [PATCH 099/101] docs(fitness): reconcile protected evidence maturity --- docs/DOCUMENTATION_FITNESS.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/DOCUMENTATION_FITNESS.md b/docs/DOCUMENTATION_FITNESS.md index c87d3d0d..5843c088 100644 --- a/docs/DOCUMENTATION_FITNESS.md +++ b/docs/DOCUMENTATION_FITNESS.md @@ -46,8 +46,8 @@ Document fitness and implementation maturity are independent. A `present_current | Autosave lifecycle observation | PRD, TRD, `docs/document-autosave.md`, lifecycle doctoring and protected autosave package/session source | `present_current` | `implemented_on_protected_main`; protected main exposes the bounded construction-time observer contract | Buyers can reconstruct saving/blocked/recovery/idle/shutdown observation, document-free snapshots, observer-failure isolation, and durable-validator coherence without treating it as an active-PR promise. | | SSR/native-form serialization | PRD, TRD, `docs/server-rendering.md`, SSR doctoring and protected editor/form source | `present_current` | `implemented_on_protected_main`; protected main includes the explicit server-value handoff and synchronous hydrated mirror | Buyers can reconstruct opt-in server serialization, hydration continuity, client-controlled submission semantics, reset behavior and host-owned auth/CSRF/persistence boundaries. | | Toolbar shortcut accessibility metadata | PRD/TRD accessibility requirements, accessibility guide/doctoring and protected toolbar source | `present_current` | `implemented_on_protected_main`; shipped bold/italic/link/undo/redo shortcuts expose truthful `aria-keyshortcuts` metadata | Accessibility metadata is tied to actual repository-level keyboard behavior rather than extension-local assumptions. | -| Revision-scoped selection evidence | selection lifecycle guide, doctoring, public handle/type contract and current replacement PR | `present_current` | `implemented_on_active_pr`; current-main replacement work is not shipped until protected integration | Atomic selection+revision evidence, privacy minimization and host-owned re-anchoring are reconstructable without promoting the active PR. | -| Document-transition evidence | transition doctoring/public contract and PR #68 | `present_current` | `implemented_on_active_pr`; the framework-independent transition-evidence branch is not protected authority yet | Previous/resulting revision lineage and privacy/provenance boundaries remain explicit while integration is pending. | +| Revision-scoped selection evidence | selection lifecycle guide, doctoring and protected public handle/type contract | `present_current` | `implemented_on_protected_main`; protected main atomically binds structural selection coordinates to the exact revision | Atomic selection+revision evidence, privacy minimization and host-owned re-anchoring are reconstructable as shipped behavior without overstating cross-revision authority. | +| Document-transition evidence | transition doctoring, public framework-independent contract and protected revision-evidence package | `present_current` | `implemented_on_protected_main`; protected main exposes object/JSON and strict UTF-8 transition evidence | Previous/resulting revision lineage and privacy/provenance boundaries are reconstructable as shipped local evidence without implying actor/time/durable-write provenance. | | THREAT_MODEL | `docs/THREAT_MODEL.md` | `present_current` | Covers current and explicitly proposed trust boundaries | Clipboard, Office, SSR/form, Yjs, model, host-authority and supply-chain threats are reconstructable. | | TEST_STRATEGY | `docs/TEST_STRATEGY.md` | `present_current` | Current deterministic evidence plus `planned` cross-engine acceptance where dependency order requires it | Test authority and claim limits are explicit rather than inferred from CI badges. | | OPERABILITY | `docs/OPERABILITY.md` | `present_current` | Current local/product responsibilities plus host-owned recovery boundaries | Conflict, collaboration, conversion and release recovery/rollback ownership are explicit. | @@ -70,11 +70,11 @@ The canonical graph must retain durable product decisions from the project conve - bounded protected-main autosave lifecycle observation with document-free distinct snapshots and observer-failure isolation; - protected-main SSR/native-form serialization with opt-in document disclosure, controlled hydration handoff, synchronous native-field mirroring, and host-owned acceptance controls; - protected-main toolbar shortcut metadata that reflects the actual cross-platform bold, italic, link, undo and redo bindings; -- revision-scoped selection and document-transition evidence as active-PR capabilities rather than protected-main claims; +- protected-main revision-scoped selection and document-transition evidence with local equality/lineage semantics and host-owned re-anchoring/occurrence provenance; - naruon `compose` / `ui.panel` modular integration without making naruon a standalone runtime dependency; - model assistance as untrusted proposed content rather than conversion or persistence authority; - accessibility, keyboard, print/export and document-fidelity evidence boundaries; -- host ownership of transport, identity, authorization, tenancy, persistence, credentials, migration, retention, deployment, durable audit and model policy; +- host ownership of transport, authentication, authorization, tenant isolation, persistence, credentials, migration, retention, deployment, durable audit and model policy; - protected-main private vulnerability reporting and coordinated disclosure with explicit evidence-minimization and no-SLA/no-certification boundaries; - strict current-schema parsing plus planned identity-only envelope routing, while migration execution remains host-owned; - real Chromium/Firefox/WebKit differential evidence as a release gate for browser-semantic clipboard security rather than a jsdom conformance claim; and @@ -90,12 +90,12 @@ The documentation pack itself is substantially complete for acquisition review, 1. Issue #74 remains `planned`: the identity-only migration-routing API must still be implemented test-first while the current parser remains strict. Its architectural decision is now present rather than hidden in issue prose. 2. Issue #66 remains `planned` behind PR #65: the dependency-locked Chromium/Firefox/WebKit differential suite must still be implemented before the rich-clipboard release line. Its release-assurance decision is now present rather than hidden in issue prose. -3. Document-transition evidence (PR #68), revision-scoped selection evidence (current replacement lane), and SafeClipboard (PR #65) remain `implemented_on_active_pr` until protected integration. Autosave lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, and SSR/native-form serialization are now `implemented_on_protected_main` and must not be described as active-only work. -4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge. At this review point protected main is at least `268ef8ec25a82edff863b4deace7d431333cd3a6`; later source movement must be refetched rather than hard-coded as timeless architecture. +3. SafeClipboard (PR #65) remains `implemented_on_active_pr` until protected integration. Autosave lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are now `implemented_on_protected_main` and must not be described as active-only work. +4. The canonical documentation branch must still reconcile its ancestry with the latest protected `main` before protected merge; protected-main identity must be refetched rather than hard-coded as timeless architecture. 5. Documentation becoming mergeable or protected-merged is not a reason for the commercial loop to stop; the next safe product, release, security, accessibility or interoperability lane must continue. ## Sufficiency decision -For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Autosave lifecycle observation, the security disclosure lifecycle, toolbar shortcut accessibility metadata, and SSR/native-form serialization are `implemented_on_protected_main`. Revision-scoped selection evidence, document-transition evidence, and SafeClipboard remain active-PR work. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. +For this active documentation branch, PRD, TRD, Architecture, ADR, UML, conceptual ERD/data model, contracts, threat model, test strategy, operability, security disclosure, and traceability are `present_current` for the durable product and accepted/planned architecture decisions reconstructed from the conversation and live repository. Autosave lifecycle observation, the security disclosure lifecycle, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are `implemented_on_protected_main`. SafeClipboard remains active-PR work. Envelope migration routing and cross-engine browser assurance are explicit Proposed ADR decisions while their implementations remain `planned`. A physical relational ERD is `not_applicable` because Inkspan deliberately owns no application persistence. No material product architecture decision identified by this review remains only in chat or issue prose. Accordingly, the **documentation design is sufficient as a proposed acquisition baseline**, but the repository is **not yet a protected-main canonical baseline** until this graph is reconciled with the latest protected source generation and passes normal protected integration. Product/release readiness must continue to be evaluated independently of documentation completeness. From 6701509ea2070264b32998a52e89a313ed8dc8bd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 02:52:08 +0900 Subject: [PATCH 100/101] test(docs): preserve active-vs-shipped wording contract --- docs/PRD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PRD.md b/docs/PRD.md index b983e498..1f538cf2 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -4,7 +4,7 @@ Status: Proposed canonical baseline ## Product definition -Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are implemented on protected `main`; this canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling, which remains a target requirement rather than a shipped claim until protected integration. Across current and proposed scope, Inkspan keeps host transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. +Inkspan is a standalone Markdown/HTML rich-text authoring and deterministic document-conversion product that can also be embedded as a modular CWL component. Protected `main` is the implementation authority for what Inkspan actually provides today. Lifecycle observation, security disclosure, toolbar shortcut accessibility metadata, SSR/native-form serialization, revision-scoped selection evidence, and document-transition evidence are implemented on protected `main`. This canonical PRD also records Active PR / Proposed requirements such as safe rich clipboard handling; such requirements are not shipped claims until protected integration. Across current and proposed scope, Inkspan keeps host transport, authentication, authorization, tenant isolation, durable persistence, credentials, migrations, retention, deployment, audit storage, and model-use policy outside the product boundary unless a future accepted versioned contract explicitly changes that division. The product promise is: **author, convert, collaborate, and prove document changes without hiding authority inside the editor.** From b00695e958bd83d400f1b0c771b230ecc3cd61b7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 03:03:32 +0900 Subject: [PATCH 101/101] docs: reconcile canonical changelog with protected main --- CHANGELOG.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69e11601..cdc35f43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,42 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim ## [Unreleased] +### Fixed +- 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 +- 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 +- Added one optional construction-time `onSnapshotChange` callback to the framework-free autosave queue and durable autosave session so hosts can observe saving, pending, blocked, recovery, idle, and shutdown state without polling or introducing a subscriber collection +- Added privacy-minimized revision-scoped selection evidence through `getSelectionRevisionEvidence()`, binding frozen ProseMirror coordinates to the SHA-256 strong revision of the exact same immutable editor state before asynchronous hashing begins +- Added privacy-minimized document transition evidence for validated previous and resulting canonical revisions through the framework-independent `revision-evidence` subpath, with object/JSON and strict UTF-8 entry points, deterministic previous-then-resulting SHA-256 derivation, frozen revision-only results, and no document body, actor, tenant, time, authorization, signature, transport, model, or durable-write claim + +### Reliability +- Lifecycle observers receive only distinct frozen document-free snapshots; observer exceptions cannot alter save ordering, conflict/failure recovery, queue outcomes, or durable-validator handoff +- Durable-session notifications expose a newly committed server validator only after it is coherent with the emitted lifecycle state, preserving host-owned atomic RFC 9110 `If-Match` semantics + +### Accessibility +- Added programmatic toolbar shortcut discoverability with WAI-ARIA `aria-keyshortcuts` for the implemented bold, italic, link, undo, and redo commands, preserving the same native-button behavior, visible labels, roving focus model, and host-owned shortcut-conflict policy +- Completed redo shortcut metadata with `Control+Shift+Z Meta+Shift+Z Control+Y Meta+Y`, matching the configured Tiptap history and collaboration behavior and exposing both `Ctrl/Cmd+Shift+Z` and `Ctrl/Cmd+Y` alternatives without adding new key handling +- Corrected extension-scoped review evidence after exact-head repository review found the existing editor-surface `Ctrl/Cmd+K` link binding in `EditorFrame`; the link button now truthfully exposes `Control+K Meta+K` while the Tiptap Link extension itself remains documented as having no default shortcut +- Preserved buyer-facing README guidance within the same validated safe-link command boundary and moved the shortcut-specific behavior contract to the authoritative accessibility and doctoring records so it is not misattributed to Tiptap +- Added deterministic regression and documentation contracts plus APA 7th doctoring for exact `Control`/`Meta` shortcut alternatives, the descriptive-only accessibility boundary, repository-level shortcut verification, and omission of unsupported shortcut claims + +### Tests +- Added test-first Node `renderToString` evidence for the missing SSR native value, controlled-over-default selection, escaping, external form ownership, no ProseMirror server construction, and opt-out non-disclosure +- Added browser-DOM handoff tests proving the field retains and updates the selected value before TipTap exists while reset-only unnamed fields remain empty ### Documentation -- Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and sixteen linked architecture decision records without inventing Inkspan-owned persistence or host authority; the newest decisions make envelope schema identity/host-owned migration routing and cross-engine browser-semantic release assurance first-class while keeping their implementations explicitly planned -- Added machine-checkable canonical-documentation decision coverage that keeps required files, ADR index links and completeness, migration-routing and browser-assurance UML/data-model/traceability evidence, physical-ERD non-applicability, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, host-vs-Inkspan authority boundaries, and work-conserving autonomous-maintenance guidance synchronized +- Added a canonical acquisition documentation spine covering product requirements, technical requirements, public interface/integration contracts, Mermaid UML, a conceptual data/evidence model, a threat model, test strategy, operability/recovery, standards/evidence traceability, and seventeen linked architecture decision records without inventing Inkspan-owned persistence or host authority; the newest decisions make envelope schema identity/host-owned migration routing, cross-engine browser-semantic release assurance, and the protected security-disclosure lifecycle first-class while keeping unimplemented capabilities explicitly planned +- Added machine-checkable canonical-documentation decision coverage that keeps required files, ADR index links and completeness, migration-routing and browser-assurance UML/data-model/traceability evidence, physical-ERD non-applicability, browser-security evidence, offline font provenance/no-runtime-font-egress, standards references, rollback sections, host-vs-Inkspan authority boundaries, implemented-vs-active-PR status, and work-conserving autonomous-maintenance guidance synchronized - Documented work-conserving autonomous-maintenance governance in `AGENTS.md` and `CLAUDE.md`: a blocked PR blocks only its lane, status/report/prompt/documentation milestones are intermediate while safe work remains, and the external scheduler owns cadence rather than becoming an Inkspan runtime capability +- Added a repository-native security disclosure and vulnerability-handling policy with supported pre-1.0 release lines, private GitHub Security Advisory routing and safe public fallback, minimized evidence guidance, explicit Inkspan-versus-host ownership boundaries, no-SLA and non-conformance claim limits, deterministic documentation tests, and APA 7th doctoring grounded in current ISO/IEC 29147:2018, ISO/IEC 30111:2019, final NIST SP 800-218 SSDF 1.1, the draft-status boundary for SSDF 1.2, and GitHub primary documentation +- Documented that revision-scoped selection evidence contains no selected text or complete document envelope, remains valid only for its exact document revision, is not a W3C `TextPositionSelector`, and leaves durable comments, authorization, persistence, collaborative anchoring, and cross-revision re-anchoring to the host +- Added an APA 7th doctoring record for the selection/revision atomicity, privacy, rollback, and interoperability boundaries grounded in ProseMirror, RFC 9110, and the W3C Web Annotation Data Model +- Added transition-evidence operator guidance and APA 7th doctoring for content minimization, W3C PROV occurrence-provenance limits, RFC 8785 canonicalization, RFC 9110 durable-validator separation, SHA-256 lifecycle evidence, framework-free packaging, rollback, and host-owned authenticated audit semantics - Added an authoritative standalone and modular MSA architecture contract with reviewable deployment, optimistic-concurrency, data-ownership, security, and acquisition-evidence diagrams and tables - Added a beginner-readable naruon compose and ui.panel integration guide covering narrow client hydration, server-selected strong validators, accessible conflict handling, host-owned Yjs lifecycle, contextual-orchestrator boundaries, and local-versus-shareable evidence - Added an opaque editing-context remount for the complete editor and autosave example, latest-generation asynchronous capture ordering, encoded document path segments, redacted recovery status, and lazy state-owned session identity to prevent cross-document state reuse @@ -20,6 +49,8 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim - Added stale-generation conflict recovery and operational save failure recovery through one reason-aware single-flight host workflow, so newer local edits cannot hide or duplicate recovery while retained work remains blocked; rejected or malformed resume attempts retain the same recovery surface until a valid resume succeeds or the editing context is disposed - Added exact-head read-only CI with fixed Ubuntu 24.04 runners, immutable action pins, explicit contributor-head checkout, disabled persisted Git credentials, and a documented merge-result compatibility boundary - Added deterministic documentation contract tests and APA 7th doctoring grounded in RFC 9110, WCAG 2.2, NIST SP 800-204, NIST SP 800-204D, OWASP ASVS 5.0.0, React, current Next.js App Router guidance, and GitHub Actions primary documentation +- Added APA 7th doctoring for the SSR native form field, including the WHATWG hidden-input/form-entry contract, React server/hydration continuity, client-controlled-data boundary, host-owned CSRF and acceptance controls, collaboration exclusion, and rollback +- Added lifecycle-observation doctoring covering bounded callback retention, local-versus-shareable evidence, durable-validator coherence, WCAG 2.2 status-message responsibilities, rollback, and APA 7 references to RFC 9110, WCAG 2.2, and optimistic concurrency research ## [0.5.29] — 2026-08-05