Ga naar hoofdinhoud

OMI Studio 1.0 Refactoring and PR Plan

Baseline: Studio eca2cf45762116e1c00a89b3397840ed89109511 and the audited 2026-09-19 OMI/PKP commits
Goal: reach 1.0.0-rc.1 and then 1.0.0 through small, independently testable, reversible pull requests.

The identifiers A01–F03 define 53 planned PR units. They are planning identifiers, not existing GitHub pull-request numbers.

1. Execution principles

  1. Contract or adapter first, call-site migration second, legacy removal last.
  2. Each PR has one primary architectural change. Mechanical moves and semantic changes should not be mixed.
  3. High-risk refactoring begins with characterization or golden fixtures.
  4. During format migration, use dual-read/new-write or shadow validation; never silently convert in place.
  5. Legacy route/store facades remain until all known consumers have moved.
  6. A rollout flag is not a compatibility strategy. Format, identity, and security changes require explicit forward and rollback behaviour.
  7. Test data is synthetic, public, or explicitly created for testing. Private manuscript titles, author data, filenames, content, and local paths do not enter Git or CI logs.

2. Dependency overview

flowchart TB
A["A: contracts and freeze"] --> B["B: core boundaries"]
A --> C["C: interoperability"]
B --> C
B --> D["D: platform hardening"]
C --> E["E: release candidate"]
D --> E
E --> F["F: 1.0 release"]

Within a phase, PR identifiers are arranged in dependency order. The register later in this document identifies work that can proceed in parallel.

3. Phase A — Architecture freeze

Exit condition: accepted compatibility policy; candidate normative schema/container/content contracts; agreed direction for /api/v1 and connector contracts; dependency-boundary lint; stable/preview/deferred support matrix.

PRGoalPrerequisiteRequired evidenceRisk
A01Freeze stable/preview/deferred 1.0 scope and the independent version axes.documentation links and support-matrix completenesslow
A02Make OMI 0.2 schema/fixture conformance mandatory OMI CI and a release artifact.A01current fixtures plus negative/future fixtures and schema checksummedium
A03Vendor the released schema into Studio and introduce OmiEnvelopeClassifier/validator in shadow mode.A02checksum-drift, valid/invalid/future classificationmedium
A04Introduce explicit open policy and future-schema quarantine/read-only handling.A03major/minor/invalid/oversize fixtures; no overwrite; raw recoveryhigh
A05Add pre-save/export validation and unknown-extension preservation.A03, A04open→save semantic equality; invalid save blocked; unknown payload preservedhigh
A06Freeze the required OMI-SPEC-100 portable-content AST candidate and add ContentCodec.A01legacy text/current PM JSON → AST → PM golden fixtures; unknown-node diagnosticshigh
A07Freeze an OMI-SPEC-330 container manifest/path/checksum/security candidate derived from the working parser.A02, A03cross-repo golden containers and hostile/corrupt package fixtureshigh
A08Define common diagnostics, fidelity, validation, and provenance base contracts.A01serialization, stable codes, redactionlow
A09Create additive /api/v1 transport foundations with error/idempotency/correlation contracts.A01contract tests and middleware orderingmedium
A10Enforce dependency direction and compatibility re-export patterns.A03, A06, A09forbidden core→UI/editor/Prisma/network import fixtureslow

Phase blockers: no owner for the OMI schema release process; insufficiently concrete OMI-SPEC-100 content grammar; unresolved SPEC-330/implementation differences; undefined stable platform/export scope.

4. Phase B — Core refactoring

Exit condition: create/open/save and primary editing/history flows are behind the application facade; Tiptap boundary is explicit; portable/persistence/UI ownership is separated; native credentials are not stored in localStorage.

PRGoalPrerequisiteRequired evidenceRisk
B01Introduce application ports and a StudioApplication facade without changing current model behaviour.A10fake repository/clock/ID-generator testsmedium
B02Move document create/open/save/close/recover behind the facade.A04, A05, B01create/open/save/reopen; invalid/future; dirty-close matrixhigh
B03Split Zustand ownership into document projection, UI state, editor session, and persistence projection.B01, B02current suite plus selector/action characterizationhigh
B04Consolidate automatic checkpoint timers into one document-scoped scheduler.B03fake-clock close/switch/reopen; no duplicate commitmedium
B05Route every Tiptap-content reader/writer through ContentCodec.A06, B01existing editor/export golden diffs and corrupt-node diagnosticshigh
B06Make new saves use the portable OMI AST; treat the pre-stable Tiptap-string form only as explicit import.A05, B05AST round-trip; experimental legacy import; future-major quarantinehigh
B07Add RevisionRepository using the current full-snapshot algorithm as the first adapter.B01, B06history/revert/integrity across adaptersmedium
B08Add crash-safe atomic save/recovery journal and opaque DocumentLocation.B02, B07fault injection at write stages; backup restore; digest conflicthigh
B09Formalize identity DB authority and the main-DB StudioPrincipal projection.A09migration rollback, idempotent ensure, drift/reconcile, auth flowshigh
B10Add platform SecureStorage and migrate native bearer tokens.B01upgrade migration, logout/revoke, absence from localStoragehigh
B11Separate account, auth identity, scholarly agent, contribution, and evidence mapping.B09no implicit email/ORCID merge; verified link/revokehigh
B12Replace string-offset proofing/tracked changes with stable-anchor/semantic-operation representation behind an adapter.B05, B06concurrent edits, Unicode/graphemes, accept/reject round triphigh
B13Remove or isolate orphaned alpha workspace state and empty domain placeholders.A10, B03, usage auditbuild/tests and no active referenceslow

B03, B05, B06, B08, and B09 deliberately remain separate rollback domains. Store ownership, file-format writing, persistence safety, and identity authority must not be changed in one PR.

5. Phase C — Interoperability hardening

Exit condition: common importer, renderer, connector, and review contracts; OJS and OMP satisfy one connector suite; publication artifacts are reproducible and validated; schema/container conformance is mandatory.

PRGoalPrerequisiteRequired evidenceRisk
C01Introduce an Importer registry with source/probe/progress/abort/diagnostics/fidelity contracts.A08, B01, B06fake importer, ambiguity/probe, abort, redaction, no mutation before commitmedium
C02Wrap OMI/DOCX/PDF/HTML/table/image/music/reference importers and fix MIDI routing.C01per-format golden fixtures, .mid/.midi, quotas/cancel/hostile corpushigh
C03Introduce Renderer registry and separate ArtifactDeliveryPort.A08, B05, B06every exporter through wrapper; delivery fake; no picker in rendererhigh
C04Remove publication-profile module augmentation from the manuscript model and build immutable RenderingContext.C03embedded-profile dual read, profile version, context goldenhigh
C05Pin renderer/validator/font/resource versions and distinguish semantic from byte reproducibility.C04repeated-build hashes, font substitution, locale/timezone, signature cross-runtimehigh
C06Create common Publishing System Connector schemas for capability/launch/submission/review/writeback receipts.A08, A09shared JSON contract fixtures across Studio/OJS/OMPhigh
C07Adapt the OJS client and plugin to the common connector API while retaining compatibility routes.C06supported OJS Docker E2E; replay/scope/files/forms/recommendations/artifactshigh
C08Adapt the OMP client and plugin to the common API with monograph/chapter extensions.C06OMP Docker E2E; assigned-chapter confinement; rounds/stage fileshigh
C09Introduce durable outbox/idempotent saga for submission, revision, review, and artifact writeback.C07, C08, B09timeout/duplicate/retry/crash, receipt reconciliation, no false rollbackhigh
C10Extract publishing-system-neutral review domain and harden anonymous projection.B11, C06role transition matrix, identity-leak corpus, EXIF/SVG, cache/log redactionhigh
C11Introduce server-issued ExecutionGrant for integrations, AI, translation, and reference managers.B09, B11, A09denied scope, selection-only payload, confidential review, expiry/replay, audit digestshigh
C12Consolidate credential storage and wrap Zotero/Mendeley/ORCID/OIDC/provider secrets consistently.B09, C11dual-read migration, encryption/key rotation, revoke, no secret logshigh
C13Adapt cloud storage to one remote object-store contract with ETag/conflict receipts.B08, C11SSRF redirects, ETag conflict, checksums, refresh, large/resumable behaviourmedium
C14Promote only proven export formats to stable; expose other formats as preview capabilities.C03–C05JATS/HTML/DOCX/PDF gates; preview-format smoke; runtime capability UIlow

Phase blockers: unavailable test images for supported PKP versions; font licensing that prevents reproducible resource bundling; no selected JATS/profile requirement; no clear owner of the common connector DTO.

6. Phase D — Platform hardening

Exit condition: every stable platform uses the same core/application suites; platform-port contracts pass; performance and accessibility budgets are agreed.

PRGoalPrerequisiteRequired evidenceRisk
D01Introduce complete platform port set: picker/filesystem/secure storage/auth handoff/updater/fonts/share/notifications.B08, B10, C03contract fakes, web/Tauri adapter tests, forbidden direct-import linthigh
D02Harden web file/session/recovery and PWA/browser fallbacks.D01Chrome/Firefox/WebKit open/edit/save/reopen, quota, denied permission, offlinemedium
D03Harden Windows/Linux/macOS Tauri artifacts and update flow.D01install, open-with, atomic save, update/rollback, signed artifacthigh
D04Harden Android SAF/auth/update/process-death behaviour.D01Android 10+ persisted permissions, large files, process death, updatehigh
D05Complete iOS/iPadOS preview adapters without stable promotion.D01simulator/device smoke, Files permission, background/resume, privacymedium
D06Set performance budgets and improve main-chunk/editor/renderer lazy loading.B03, B05, C0310k/120k/500k benchmarks, heap/editor count, bundle budgetmedium
D07Make critical accessibility journeys release-blocking.B03, D02keyboard-only create/edit/review/export, axe, screen-reader smoke, zoom/contrastmedium
D08Publish stable/preview platform capability manifest and runtime display.D02–D07artifact capability snapshot and documentation/runtime equalitylow

7. Phase E — Release Candidate

Exit condition: 1.0.0-rc.1 artifacts produced from one commit; every mandatory gate green; no P0/P1 data-loss/security/anonymity blocker; acceptance report completed.

PRGoalPrerequisiteRequired evidenceRisk
E01Build common hostile-input/security corpus and fuzz harness.A04, A07, C02, C10ZIP bombs/traversal, XXE/entities, SVG/script, SSRF, malformed JSON, log redactionhigh
E02Create exact-commit RC aggregator workflow with no path filters.all A–D gatesfull matrix and artifact/SBOM/provenance hashesmedium
E03Run synthetic/public acceptance corpus and local-only private acceptance protocol.C14, D08, E01format/platform journeys; only content-free private metrics/results leave the devicemedium
E04Freeze API/schema/container/connector compatibility baseline and generate release documentation.E02, E03breaking-diff detector, documentation links, fixture checksumshigh
E05Build and test 1.0.0-rc.1 artifacts.E02–E04exact-tag mandatory gates, install/update/rollback, signatureshigh

RC soak and exit

  • Use a predetermined soak period on every stable platform.
  • Any P0/P1 defect requires a new RC.
  • No waiver is permitted for data loss, credential leakage, anonymity breach, schema corruption, or signature mismatch.
  • P2 may remain only with an owner and documented workaround when it does not violate a stable contract.
  • Private acceptance manuscripts remain local. CI/Git receives only content-free metrics and synthetic minimal reproducers.

8. Phase F — 1.0 release

PRGoalPrerequisiteRequired evidenceRisk
F01Promote the last unchanged RC commit to 1.0.0.signed RC exitartifact identity or justified reproducible rebuildlow
F02Publish support/deprecation/security-response channels and compatibility fixture package.F01public links/checksums/install smokelow
F03Open the 1.0.x hardening milestone for compatible changes only.F01issue-template policylow

1.0.0 must not contain a functional fix that was not in the final RC. Any code change requires another RC.

9. Dependency register

PRDirect dependencyUseful parallelism
A01
A02A01A08, A09
A03A02A06, A08, A09
A04A03A06, A07
A05A03, A04A07–A10
A06A01A02–A05, A08–A10
A07A02, A03A04–A06, A08–A10
A08A01A02–A07, A09–A10
A09A01A02–A08
A10A03, A06, A09
B01A10
B02A04, A05, B01B09
B03B01, B02B09, B10
B04B03B05, B09–B11
B05A06, B01B09–B11
B06A05, B05B09–B11
B07B01, B06B09–B11
B08B02, B07B09–B12
B09A09B02–B08
B10B01B03–B09
B11B09B03–B08, B10
B12B05, B06B07–B11
B13A10, B03B04–B12
C01A08, B01, B06C06
C02C01C03, C06
C03A08, B05, B06C01, C06
C04C03C01–C02, C06
C05C04C06–C08
C06A08, A09C01–C05
C07C06C08, C10
C08C06C07, C10
C09C07, C08, B09C10–C14
C10B11, C06C07–C09
C11B09, B11, A09C07–C10
C12B09, C11C09–C10, C13–C14
C13B08, C11C09–C12, C14
C14C03–C05C09–C13
D01B08, B10, C03
D02–D05D01one another
D06B03, B05, C03D02–D05, D07
D07B03, D02D03–D06
D08D02–D07
E01A04, A07, C02, C10Phase D
E02all A–D gatesE01 and E03 preparation
E03C14, D08, E01E02
E04E02, E03
E05E02–E04
F01RC exit
F02F01F03 preparation
F03F01

10. Why the larger refactors are justified

RefactorWhy a small patch is insufficientWhy a rewrite is unnecessary
Tiptap ↔ OMI content boundaryindependent consumers parse the same serialized representationkeep editor/extensions/parsers, place them behind one codec
Zustand/application splitglobal store ownership prevents platform-independent testing and mixes timers/persistence/UIcharacterize actions, then delegate incrementally; selectors remain
history repositoryfull snapshots scale poorly and history is duplicatedkeep revision IDs, semantics, revert, integrity; change storage behind port later
identity authoritytwo schemas contain overlapping user/session/identity conceptskeep working identity DB and bridge; add projection/reconciliation
common connector APIparallel OJS/OMP DTOs multiply with every new publishing systemkeep both clients/plugins as adapters
review projectionanonymity is a security boundary, not a UI preferencekeep server allowlist/sanitizer and strengthen it with contracts/corpus

11. Rollback strategy

  • Schema/open: A03 shadow validation is independently reversible. After A04, the old parser is only an explicit legacy-import path. Newer saved formats are never silently downgraded.
  • Content AST: B05 keeps the wire representation unchanged while consumers move behind the codec. B06 changes the writer generation. Rollback treats new files as read-only/recovery input rather than overwriting them with an older writer.
  • Store: compatibility selectors/actions preserve UI while slices delegate to application services.
  • Database/identity: expand → migrate → contract. Additive/nullable fields first, dual-read and reconciliation second, destructive cleanup last. Every migration requires tested restore/down procedure.
  • Connector/outbox: adapters may be selected by controlled rollout, but queued outbox intent must never be lost. Rollback workers must understand both active payload generations during transition.
  • Platform: adapter selection occurs at composition roots. A legacy adapter remains only while it still satisfies the current security policy.

12. Milestones

MilestoneIncludesExit artifact
1.0-architecture-freezeA01–A10accepted/deferred ADRs and pinned schema/container/content/API candidates
1.0-core-boundariesB01–B13application facade, portable content, persistence/history/identity boundaries
1.0-interoperabilityC01–C14common import/render/connector/review contracts and evidence
1.0-platform-hardeningD01–D08stable platform matrix and budgets
1.0-rc.1E01–E05signed exact-commit RC plus evidence manifest
1.0.0F01–F03unchanged promoted RC plus public compatibility/support policy

13. Minimum issue/PR template

Each architecture migration PR should state:

  • contract/ADR reference;
  • dependency boundary before and after;
  • preserved current behaviour and intentional behaviour change;
  • affected stable/preview capability;
  • synthetic/public fixture reference;
  • rollback trigger and data-compatibility note;
  • test evidence plus performance/security impact;
  • documentation/specification mismatch closed or intentionally left open.

This decomposition is intentionally conservative. The 1.0 programme should optimize for reversible convergence on explicit contracts, not for the visual neatness of one large refactor.