Skip to content

docs(adrs): ADR 0103 — language-neutral contracts, React-first, .NET-core/Rust-edge - #222

Merged
ctwoodwa merged 2 commits into
mainfrom
chore/adr-0103-react-first-offline
May 31, 2026
Merged

docs(adrs): ADR 0103 — language-neutral contracts, React-first, .NET-core/Rust-edge#222
ctwoodwa merged 2 commits into
mainfrom
chore/adr-0103-react-first-offline

Conversation

@ctwoodwa

@ctwoodwa ctwoodwa commented May 31, 2026

Copy link
Copy Markdown
Contributor

Status: DRAFT — awaiting pre-merge soundness council per ADR 0069 §D1

ADR 0103 records CIC's ratified strategy direction (BDFL per ADR 0018), resolving the long-running UI/backend strategy fork. Strategic content is already ratified by CIC (2026-05-31, verbatim: "Offline is essential, tech stack is less important but needs to be mit and best oss support the priority" + "MIT + permissive-compatible" + "Accepted"). This PR is held in DRAFT only for a technical-soundness / cited-symbol-drift check — not a re-litigation of the strategic call.

The five decisions

  • D1 — Language-neutral contracts are the source-of-truth. Both .NET and TS are generated targets. (Open follow-up: pick the contract-definition format — neutral IDL/TypeSpec vs TS-first vs C#-first.)
  • D2 — React-first expression. Offline is the non-negotiable product requirement; Blazor Server (Bridge shell, ADR 0033) is online-only by construction, so the Tauri-React local-first desktop (sunfish/apps/desktop/, SQLite + Loro CRDT + offline write-queue, ADR 0086) is the canonical product client. Blazor continues as a contract-generated second target + platform showcase, not a parallel product.
  • D3 — .NET stays the authoritative core; Rust owns the edge tier it already owns. No ideological rewrite. Protects the live-auth launch gate (docs(contracts): M1 DataEntry contracts — FormField, TextField, SelectField, DateField, NumberField, CheckboxField #272) and the shipped .NET auth substrate (ADRs 0097/0099).
  • D4 — Standing dependency criterion: MIT + permissive-compatible (Apache-2.0/BSD/ISC; no copyleft), best-OSS-support as tiebreak. Extends ADR 0018 (output-license → dependency-selection rule). Excludes proprietary UI vendors (Telerik/Syncfusion/Infragistics) → reinforces shadcn/Radix on React. Adds a CI license-gate checklist item.
  • D5 — Triggers the ADR 0086 adoption-posture flip (γ→α) to exit the confirmed β-trap (PM UI built twice). ADR 0048 (MAUI) → showcase/secondary; supersession candidate on full α.

§A0 cited-symbol verification (done 2026-05-31)

  • ADR citations verified to exist on disk: 0012, 0014, 0017, 0018, 0028, 0030, 0033, 0048, 0077, 0086, 0090.
  • Package paths verified: shipyard/packages/{ui-core, ui-adapters-blazor, ui-adapters-blazor-a11y, ui-adapters-react, ui-react}; sunfish/apps/{desktop, web}.
  • ui-core interface FQNs deferred to the D1 codegen follow-up (no premature pin).

Registry / index caveat (housekeeping, not blocking)

docs/adrs/STATUS.md, INDEX.md, GRAPH.md are marked "auto-generated by tools/adr-projections/project.py — do not edit by hand." That generator is not present anywhere in the committed tree (verified: not in worktree, not in the main checkout, not gitignored, not git-tracked; no CI workflow regenerates it). Rather than hand-edit files marked do-not-edit, this PR commits only the ADR source (the frontmatter is the source-of-truth the projections derive from). The README.md index table is independently stale (stops at 0072). Locating/restoring the projection generator + refreshing the registries + README index is filed as a separate housekeeping item — out of scope for this PR.

Council ask (3 councils — pre-merge, ADR 0069 §D1)

  • sec-eng — license-gate posture; no secrets/PII surface (none expected; governance ADR).
  • .NET-architect — .NET-core-stays / Rust-edge tier split soundness; no churn pressure on shipped 0097/0099 auth.
  • frontend-architect (MANDATORY here) — surface-selection scope (React-first / Tauri-React canonical client / Blazor-as-second-target).

Auto-merge will be armed (--squash --auto) only on 3-council GREEN.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added architectural decision record (ADR 0103) documenting framework standardization, service architecture decisions, and dependency licensing constraints for the project.

….NET-core/Rust-edge

Records CIC's ratified strategy direction resolving the UI/backend fork.

Five decisions:
- D1 language-neutral contracts are source-of-truth; .NET and TS both generated.
- D2 React-first expression; offline-essential selects Tauri-React desktop as
  the canonical product client; Blazor is a second generated target + showcase.
- D3 .NET stays the authoritative core, Rust owns the edge tier it already owns;
  no ideological rewrite (protects the live-auth launch gate).
- D4 standing dependency criterion MIT plus permissive-compatible
  (Apache-2.0/BSD/ISC, no copyleft); excludes proprietary UI vendors;
  extends the governance/license posture ADR.
- D5 triggers the offline-desktop adoption-posture flip; MAUI Blazor becomes
  showcase/secondary, supersession candidate on full adoption.

Status Accepted, ratified by CIC (BDFL) 2026-05-31. Opening as DRAFT pending the
ADR-0069 pre-merge soundness council (sec-eng plus .NET-architect plus frontend-arch).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

PR 222 adds ADR 0103, documenting a governance decision to establish language-neutral UI/domain contracts as the authoritative source of truth, express UI-first via React with Blazor as generated showcase, split backend tiers between .NET core and Rust edge/on-device, and enforce MIT + permissive-compatible-only dependency licensing. The document includes implementation checklist, compatibility plan, open questions, revisit triggers, and pre-merge/pre-acceptance quality gates.

Changes

ADR 0103: Language-Neutral Contracts, React-First Approach, and Backend Tier Split

Layer / File(s) Summary
ADR framing and cited-symbol audit
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
ADR 0103 frontmatter, governance tier, and cited-symbol audit establish scope and verify predecessor ADRs and contract/toolchain references.
Decision context and options
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Context drivers (offline-essential, OS reach, MVP protection, tech-stack neutrality, licensing posture, no duplication) and alternatives A/B/C with recommended option C.
Core decision and commitments
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Adopted decision D1–D5: neutral contracts, React-first expression with Blazor generated, .NET core + Rust edge split, MIT + permissive licensing rule.
Consequences and risk assessment
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Positive and negative consequences; security/privacy impact affirms unchanged auth threat model while tightening supply-chain licensing.
Compatibility plan and implementation checklist
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Execution strategy (Bridge unchanged, Tauri canonical client, ADR 0086 γ→α flip, consistent React distribution); codegen toolchain, CI licensing gate, follow-on ADRs, vendor shim, Blazor page staging.
Future decision boundaries and triggers
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Open questions on contract format, ADR 0086 timing, offline scope; revisit triggers for offline mandatory status, .NET core migration, licensing availability, toolchain practicality.
Governance constraints and pre-acceptance audit
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Pre-merge council constraints (transitive license closure, asset/font exceptions, generated TS contracts-only, offline-Blazor rationale, adapter drift, React-first bias); pre-acceptance audit checklist (AHA pass, kill triggers, rollback, confidence, cited-symbol verify, anti-pattern scan, revisit triggers).
References
docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md
Links to predecessor/sister ADRs, roadmap items, and existing code substrates.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A contract drawn in neutral ground,
React and Rust now spring-aligned,
Offline blooms with .NET crowned,
MIT's permissive thread unwinds—
Governance hopped, decisions bind!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description is comprehensive and well-structured with strategic context, five clear decisions, verification steps, and council requirements; however, it deviates significantly from the repository's template structure (missing ICM stage, affected packages checkboxes, and build/test checklist items). Align the description with the repository template by adding ICM stage designation, checking affected packages (Repo infrastructure / CI / docs only likely applies), and confirming relevant checklist items are addressed (docs update confirmed; others may be N/A for governance ADR).
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: ADR 0103 documenting the strategy decision for language-neutral contracts, React-first approach, and .NET-core/Rust-edge tier split.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/adr-0103-react-first-offline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

All three pre-merge councils returned GREEN with non-blocking findings.
Folded the two factual ADR-text corrections plus a forward-looking
council-folds capture:

- correct the contract-mirror claim: no inherited automated C#-to-TS
  codegen mirror exists today; standing up and validating emit fidelity
  is in-scope for the contract-format follow-up, not an assumption
- clarify the Tauri-React client path label across the two sister ADRs
- record license-gate transitivity, contracts-only codegen invariant,
  offline-Blazor ruled-out citation, adapter-drift, and TS-bias notes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ctwoodwa
ctwoodwa marked this pull request as ready for review May 31, 2026 20:41
@ctwoodwa
ctwoodwa enabled auto-merge (squash) May 31, 2026 20:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md`:
- Line 174: The word "councilled" in the sentence "A future councilled migration
ADR proposes relocating the authoritative core off .NET (would reopen D3)." is a
typo; update that phrase to the project's preferred form (e.g.,
"council-approved" or "counseled"/"counciled" depending on style) so it reads
consistently (for example: "A future council-approved migration ADR proposes
relocating the authoritative core off .NET (would reopen D3)."). Ensure the
replacement preserves the sentence meaning and style consistent with other ADRs.
- Around line 212-213: The doc uses inconsistent package root paths: replace the
short form `packages/ui-core`, `packages/ui-adapters-react`,
`packages/ui-react`, `packages/ui-adapters-blazor` with the canonical path used
elsewhere (e.g., `shipyard/packages/ui-core`,
`shipyard/packages/ui-adapters-react`, `shipyard/packages/ui-react`,
`shipyard/packages/ui-adapters-blazor`) so all references match the earlier
`shipyard/packages/...` style; update the list in the block containing
`sunfish/apps/desktop/` and the four package entries to the canonical
`shipyard/packages/...` form.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1c639cce-604e-41bd-96ea-a28bc06ed4f7

📥 Commits

Reviewing files that changed from the base of the PR and between 037f892 and 8765579.

📒 Files selected for processing (1)
  • docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md


## Revisit triggers

- A future councilled migration ADR proposes relocating the authoritative core off .NET (would reopen D3).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix spelling in revisit trigger wording.

“councilled” is likely a typo; please normalize to the project’s intended form (e.g., “council-approved” / “counciled”) for consistency across ADRs.

🧰 Tools
🪛 LanguageTool

[grammar] ~174-~174: Ensure spelling is correct
Context: .... --- ## Revisit triggers - A future councilled migration ADR proposes relocating the a...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md`
at line 174, The word "councilled" in the sentence "A future councilled
migration ADR proposes relocating the authoritative core off .NET (would reopen
D3)." is a typo; update that phrase to the project's preferred form (e.g.,
"council-approved" or "counseled"/"counciled" depending on style) so it reads
consistently (for example: "A future council-approved migration ADR proposes
relocating the authoritative core off .NET (would reopen D3)."). Ensure the
replacement preserves the sentence meaning and style consistent with other ADRs.

Comment on lines +212 to +213
- `sunfish/apps/desktop/` — Tauri v2 + React 19 local-first client (offline-capable).
- `packages/ui-core`, `packages/ui-adapters-react`, `packages/ui-react`, `packages/ui-adapters-blazor`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use one canonical package root path in references.

Line 213 lists packages/..., while earlier audit lines use shipyard/packages/.... This inconsistency can send readers to the wrong location during verification.

Suggested doc fix
-- `packages/ui-core`, `packages/ui-adapters-react`, `packages/ui-react`, `packages/ui-adapters-blazor`.
+- `shipyard/packages/ui-core`, `shipyard/packages/ui-adapters-react`, `shipyard/packages/ui-react`, `shipyard/packages/ui-adapters-blazor`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `sunfish/apps/desktop/` — Tauri v2 + React 19 local-first client (offline-capable).
- `packages/ui-core`, `packages/ui-adapters-react`, `packages/ui-react`, `packages/ui-adapters-blazor`.
- `sunfish/apps/desktop/` — Tauri v2 + React 19 local-first client (offline-capable).
- `shipyard/packages/ui-core`, `shipyard/packages/ui-adapters-react`, `shipyard/packages/ui-react`, `shipyard/packages/ui-adapters-blazor`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adrs/0103-language-neutral-contracts-react-first-offline-tier-split.md`
around lines 212 - 213, The doc uses inconsistent package root paths: replace
the short form `packages/ui-core`, `packages/ui-adapters-react`,
`packages/ui-react`, `packages/ui-adapters-blazor` with the canonical path used
elsewhere (e.g., `shipyard/packages/ui-core`,
`shipyard/packages/ui-adapters-react`, `shipyard/packages/ui-react`,
`shipyard/packages/ui-adapters-blazor`) so all references match the earlier
`shipyard/packages/...` style; update the list in the block containing
`sunfish/apps/desktop/` and the four package entries to the canonical
`shipyard/packages/...` form.

@ctwoodwa
ctwoodwa merged commit 8e9cb22 into main May 31, 2026
6 checks passed
@ctwoodwa
ctwoodwa deleted the chore/adr-0103-react-first-offline branch May 31, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant