Skip to content

Releases: Therealsboy8/Inventivus

Inventivus V1.9.1

Choose a tag to compare

@Therealsboy8 Therealsboy8 released this 07 Sep 18:01
8fe0fd3

Inventivus

Engineering mission control — a local-first Windows desktop application for
engineering calculators, machine architectures, native app overlays, version
control, and a built-in AI assistant named Athena.

Inventivus is an Electron app. A React + TypeScript SPA runs in the renderer, a
Fastify + SQLite backend runs as a child process of the Electron main process, and
everything — projects, simulation history, git repos, encrypted credentials — stays
on the user's machine. There is no hosted application server.


Changelog

v1.9.1 — 6 September 2026

Security and production-readiness release. Focus: making a payment
unconditionally provable, tightening the shipped attack surface, and keeping UI
state consistent across the whole app.

Critical: a payment is now provable even if activation never completed

v1.8.8 bound the buyer's GitHub account to their Stripe customer — but only when
/licence/claim succeeded, and that call runs on the customer's machine after a
inventivus:// deep link. Every way that hand-off could fail (app closed before
the browser redirected, protocol handler not registered, network dropped, or the
earlier activation bug) left a paying customer with no binding at all, whose
"Sign in with GitHub to restore" correctly reported no subscription found. The
only fix was hand-writing KV keys. Three independent changes close that gap:

  • The GitHub identity is now written to permanent Stripe objects. Checkout
    stamps it onto the subscription and customer (and client_reference_id),
    not just the short-lived Checkout Session. Stripe itself now holds the binding.
  • Provisioning happens on payment, not only on claim. The issuer acts on the
    checkout.session.completed webhook — server-to-server, so no customer-side
    failure can skip it. Idempotent with the claim path; whichever lands first
    wins. An unpaid session provisions nothing, and an existing Enterprise record
    is never downgraded.
  • Restore falls back to Stripe when the local link is missing. If no KV link
    exists, the issuer searches Stripe by GitHub identity and rebuilds the record.
    Only active/trialing subscriptions qualify, so a cancelled plan is never
    resurrected. Payment alone is now sufficient proof of purchase.

Security hardening

  • The shipped renderer no longer permits eval() or inline script. The CSP
    was one literal <meta> tag carrying 'unsafe-inline' 'unsafe-eval' in
    script-src — required by Vite's dev server, and therefore shipped to every
    install. Since Athena renders model output into that window, this was a live
    concern. The policy is now injected per environment: dev keeps what HMR needs,
    the packaged build ships script-src 'self'. Same fix for the HUD overlay,
    which floats over other applications and carries the local API token.
    object-src, frame-src, base-uri and form-action are pinned closed.
  • The licence issuer is rate-limited. It is a public origin holding the
    Stripe secret key and had no metering on any endpoint. Seat-granting
    (/team/join), selling (/checkout) and every Stripe-amplifying path
    (/licence/claim, /licence/refresh, the GitHub poll) are now bounded
    per client address, with Retry-After. Stripe's own webhook is deliberately
    exempt (it retries on non-2xx), and a KV failure fails open so a broken
    limiter cannot take checkout down with it.

Consistency: state is shared across the app

  • An open workspace stays open. It lived in useState on the project page,
    so navigating to another tab and back showed "Select a Workspace" and looked
    like the work had been closed. Active workspace and active project are now
    persisted server-side in SQLite, so they survive navigation, a reload, and the
    app being closed and reopened. Deliberately an allowlisted set of keys, not a
    general key/value store.

Fixes

  • Local-model crashes explain themselves. An Ollama GPU/CUDA failure used to
    surface as a raw HTTP 500 dump quoting Windows' stack-buffer-overrun text
    ("could potentially allow a malicious user to gain control") — alarming,
    misleading, and unactionable. Provider failures are now mapped to plain
    language with a concrete next step (update drivers, restart Ollama, run a
    smaller model, start Ollama, pull the model, check the API key), with the
    technical detail kept separate. Applies to every AI path, not just chat.
  • One version number. /api/health and the About panel each hard-coded
    0.1.0, so a release bumped the installer and left the app reporting the old
    version. Both now derive from package.json.
  • yarn verify:editions additionally asserts the packaged version, the baked-in
    issuer URL and public key, and the strict CSP in both editions.

v1.8.8 — 6 September 2026

Critical: subscriptions now survive reinstalls, updates, and new machines

Previously a customer's Pro/Enterprise status lived only in a local licence
token. A reinstall, an app update that reset app-data, or moving to a new machine
wiped that token — and there was no way to prove ownership again, so paying
customers silently dropped to Free with no recourse. Fixed end to end:

  • Durable proof-of-purchase via GitHub. Every purchase now binds the buyer's
    GitHub account to their Stripe customer in the issuer (captured at checkout).
    A new "Restore purchase — sign in with GitHub" control on the Upgrade page
    re-grants the subscription on any machine, from the customer's GitHub account
    alone — no local state required. One click, and the install is linked so future
    updates/reinstalls self-restore.
  • Recovery for customers who paid earlier. Signing in with GitHub while a
    licence is installed links that purchase to the account, so pre-existing
    customers (including the first testers) become restorable too.
  • Cancellation alerts + faster propagation. The issuer now exposes a
    signature-verified Stripe webhook (/webhooks/stripe). It updates the stored
    subscription status the moment Stripe reports a change and posts a merchant
    alert to a configured Slack/Discord webhook on cancellation — Stripe's own
    emails only notify the customer, not the merchant. Entitlement is still decided
    by live Stripe polling, so the webhook is never a single point of failure.
  • Setup steps: issuer/SUBSCRIPTION-PERSISTENCE.md.
  • Added 9 issuer tests (solo restore, cancelled-subscription refusal, link-at-
    token, GitHub rename, webhook signature + notify); 1725 tests total.

v1.8.7 — 6 September 2026

Critical: payment activation and subscription management

Payments now complete on customer machines. Previously a customer could pay
through Stripe Checkout and never receive their features, because the app was
never told the payment succeeded — and with no recorded licence, the "Manage
subscription" button never appeared, leaving customers unable to cancel. Root
cause and fix:

  • Checkout return had no path back into the app. Stripe Checkout opens in the
    customer's browser, so the app cannot see the redirect that carries the
    session_id needed to claim the licence. The issuer now serves a /return
    landing page that hands the session id back to the app through the
    inventivus://billing deep link (with an on-screen activation code and copy
    button as a manual fallback). The app claims the licence automatically on
    receipt, installs the signed token, and switches to the paid tier.
  • inventivus:// links launched a second app instance instead of reaching the
    running one.
    Added the Electron single-instance lock, without which the
    second-instance handler never fires on Windows — so a customer who had the
    app open when they paid would spawn a colliding second process and lose the
    deep link entirely. This was the difference between "payment activates" and
    "payment silently lost" for the common case.
  • Subscription management/cancellation now works. "Manage subscription"
    appears once a real licence is installed and opens the Stripe Customer Portal
    via the issuer (authenticated by the licence token, so no local Stripe key is
    needed). The portal's return link deep-links inventivus://billing?refresh=1,
    so a cancellation or plan change is reflected in the app within seconds rather
    than on the next hourly refresh.
  • Added issuer tests for the /return, /portal-return, and /cancelled
    landing pages and for the checkout success_url wiring (1716 tests total).

v1.8.6 — 6 September 2026

Bug fixes

Workspace creation

  • Fixed EasyEDA Pro .eprj (and .eprj2, .elib) files being rejected at workspace creation with "file type not supported". The extension whitelist in server/utils/path-safety.ts had drifted out of sync with the app catalog and was missing every EasyEDA format plus ~40 other catalog extensions (.kicad_pro, .fcstd, .prjpcb, .sldprt, and more). Added a regression test that enumerates the full catalog so this class of bug cannot silently reappear.

Onboarding

  • The AI setup step is now skippable. Users without Ollama or an API key can click "Skip for now" and configure AI later in Settings → AI Provider. The app opens normally in the meantime; document analysis returns a clear "no AI configured" message rather than failing silently.
  • Added a collapsible step-by-step setup guide per provider (install commands, model pull commands, exact URLs, port numbers) shown inline on the AI step.
  • Rewrote the "connection failed" advice into numbered, actionable troubleshooting steps for each provider.

Team / sharing

  • Free-tier project-share cap could be bypassed by using the bulk share path (POST /api/team/share/apply with no project_id). Fixed: bulk path now pre-counts and enforces the...
Read more

Inventivus v1.8.6

Choose a tag to compare

@Therealsboy8 Therealsboy8 released this 06 Sep 20:13
8fe0fd3

Inventivus

Engineering mission control — a local-first Windows desktop application for
engineering calculators, machine architectures, native app overlays, version
control, and a built-in AI assistant named Athena.

Inventivus is an Electron app. A React + TypeScript SPA runs in the renderer, a
Fastify + SQLite backend runs as a child process of the Electron main process, and
everything — projects, simulation history, git repos, encrypted credentials — stays
on the user's machine. There is no hosted application server.

Two small cloud pieces exist and are optional: a PartyKit room for real-time
collaboration, and a Cloudflare Worker licence issuer that signs Pro tokens
after a Stripe webhook. Neither holds project data.


Changelog

v1.8.6 — 6 September 2026

Bug fixes

Workspace creation

  • Fixed EasyEDA Pro .eprj (and .eprj2, .elib) files being rejected at workspace creation with "file type not supported". The extension whitelist in server/utils/path-safety.ts had drifted out of sync with the app catalog and was missing every EasyEDA format plus ~40 other catalog extensions (.kicad_pro, .fcstd, .prjpcb, .sldprt, and more). Added a regression test that enumerates the full catalog so this class of bug cannot silently reappear.

Onboarding

  • The AI setup step is now skippable. Users without Ollama or an API key can click "Skip for now" and configure AI later in Settings → AI Provider. The app opens normally in the meantime; document analysis returns a clear "no AI configured" message rather than failing silently.
  • Added a collapsible step-by-step setup guide per provider (install commands, model pull commands, exact URLs, port numbers) shown inline on the AI step.
  • Rewrote the "connection failed" advice into numbered, actionable troubleshooting steps for each provider.

Team / sharing

  • Free-tier project-share cap could be bypassed by using the bulk share path (POST /api/team/share/apply with no project_id). Fixed: bulk path now pre-counts and enforces the cap.
  • Task delete (DELETE /api/team/tasks/:id) had no authorisation — any team member could delete any task. Fixed: only the task creator or a team owner may delete.
  • POST /api/team/events?month= had no format validation; an unvalidated value was used as a SQL LIKE operand, returning all events. Fixed: reject anything not matching YYYY-MM.
  • Optional fields on events and tasks (description, time, assigned_to_member_id) were stored as empty strings instead of NULL, breaking IS NULL queries. Fixed to store NULL.
  • Task unassign was impossible — assigned_to_member_id only accepted a string, not null. Fixed: accepts z.string().nullable().
  • Post display-name fallback used the team name instead of member_id. Fixed.

Payments / Stripe

  • customer.subscription.deleted webhook cleared tier and status but left subscription_id set. Subsequent subscription refresh and portal calls would then attempt to operate on the deleted subscription, returning 402/404 from Stripe. Fixed: null out subscription_id on deletion.
  • Success page copy said "Pro subscription is active" for all plans, including Enterprise customers. Fixed to neutral wording.

Version control

  • Data loss: renaming a workspace then running a scoped commit silently dropped the renamed workspace's manifest entry (matched by name instead of stable repo_path), causing pruneOrphans to delete the file from the repository. Fixed: carry-forward matches by repo_path. Added a regression test.
  • POST /vcs/unstage returned a raw 500 stack trace when called on a file that was never committed to HEAD. Fixed: returns 400 with the git error message.
  • Commit error detection in VersionControl.tsx matched (e as Error).message.includes('409') — any error message containing "409" would show "Nothing to commit" instead of the real error. Fixed to e instanceof ApiError && e.status === 409.
  • stageAll() returned the count of all files with any status rather than files newly staged. Fixed.

Cross-domain checking (core feature)

  • disciplineOf returned 'other' for EDA, firmware, and CAD nodes not yet placed in a container, in three separate locations: drift.ts, consequence.ts, and inference.ts. This silently excluded real cross-discipline connections from drift reports, consequence assessments, and the inference brief sent to the AI model — the most critical output of the system. Fixed in all three with a detector-based fallback.
  • EasyEDA Pro document detector ID was hardcoded to 'easyeda-schematic' instead of 'document-projection', breaking the provenance chain for .eprj files in drift detection. Fixed.
  • Support-part warnings were emitted twice in EasyEDA Pro document detection (once in warnings, once via omitted). Fixed.
  • Detection warnings were concatenated twice into the machine-links response, doubling every warning shown to the user. Fixed.
  • partStates was not passed to computeStaleness in the /inference endpoint (unlike /staleness), so CAD parts from container documents were always shown as current to the AI model regardless of actual state. Fixed.
  • Inference test fixture DRIFT was missing required revised and consequences fields, causing tests to exercise the wrong struct shape. Fixed.

Repository layout

.
├── inventivus/          ← the actual product. Everything below this line is here.
├── memory/PRD.md        Original product requirements and backlog
├── backend/             Emergent scaffold (FastAPI "Hello World" + Mongo) — unused
├── frontend/            Emergent scaffold (CRA + shadcn/ui starter)      — unused
├── tests/               Empty pytest package left by the scaffold
└── test_result.md       Scaffold testing-protocol file

backend/, frontend/, and tests/ are leftovers from the project generator. They
are not wired into the desktop app and can be ignored (or deleted) — the Fastify
backend the app actually runs is inventivus/server/.


Quick start

Requires Node 20+ and Yarn 1.x.

cd inventivus
yarn install
yarn dev

yarn dev runs three things concurrently: the Vite dev server on :5173, a
TypeScript build of the Electron main + preload into dist-electron/, and Electron
itself — which spawns the Fastify backend on a free port.

First launch opens the onboarding wizard. To skip the paywall while developing:

yarn dev:unlocked

Full setup walkthrough, including where each Stripe key goes:
inventivus/SETUP.md.
Deeper reference on architecture and internals:
inventivus/README.md.


Stack

Layer Tech
Shell Electron 43 (contextBridge IPC, no nodeIntegration)
Renderer React 18 · TypeScript · Vite 6 · Tailwind CSS
State Zustand (global) · TanStack Query (server)
Graph / canvas React Flow
Backend Fastify 5, spawned as a child process on launch
Storage SQLite via better-sqlite3 (WAL + FTS5 full-text search)
Version control isomorphic-git — real git repos per project
Collaboration Yjs + PartyKit (y-partykit)
Native interop koffi FFI for Win32 window tracking
AI Ollama · LM Studio · OpenAI-compatible · Anthropic
Payments Stripe Node SDK + Ed25519-signed licence tokens
Packaging electron-builder → Windows NSIS installer

What's in the app

  • Mission — dashboard and telemetry across projects.
  • Calculators — truss FEM, beam, buckling, and co-simulation, with sandboxed
    controller expressions and live charting.
  • Machines — visual architecture layout wired to simulation runs.
  • Integrations — register any executable (CAD tool, simulator, terminal),
    launch it, and park a frameless HUD window in front of it. The HUD is a genuine
    second window owned by the launched app, not a reparented overlay — see
    SETUP.md § "The HUD is not an overlay".
  • Version control — git plus entity-level history, mirrored to a workspace.
  • Athena — full-page chat and a floating dock, SSE-streamed from the local
    backend so API keys never reach the renderer.
  • Projects — CRUD, invites, join flow, status control, GitHub sign-in via
    device flow.
  • Global search — SQLite FTS5 behind a Ctrl/+K
    command palette.

Editions and the free/Pro split

Two builds ship from one codebase with a single branch taken:

  • Standard — free tier with feature gates (calculators, machines, HUD live help)
    and quantity caps (5 projects, 3 integrations).
  • Unlocked — same code, resolveEntitlement short-circuits to Pro.

Version control and collaboration are free on purpose: a lapsed subscription must
never appear to have eaten someone's work. Limits are enforced on creation only,
so a user who drops from Pro keeps everything they already have.

Pro is proved by an Ed25519-signed licence token minted by the issuer worker
after a Stripe webhook — never by a local database column. The app embeds only the
public key, so it can verify a licence but cannot mint one. Enforcement is
server-side: gated routes return 402 regardless of what the UI renders.


Building the installers

cd inventivus
yarn package:standard   # → release/standard/Inventivus-Setup-0.1.0.exe
yarn...
Read more

Inventivus v1.0.0

Choose a tag to compare

@Therealsboy8 Therealsboy8 released this 01 Sep 01:49
8fe0fd3

Inventivus

Engineering mission control — a local-first Windows desktop application for
engineering calculators, machine architectures, native app overlays, version
control, and a built-in AI assistant named Athena.

Inventivus is an Electron app. A React + TypeScript SPA runs in the renderer, a
Fastify + SQLite backend runs as a child process of the Electron main process, and
everything — projects, simulation history, git repos, encrypted credentials — stays
on the user's machine. There is no hosted application server. Your information is safe.


Repository layout

.
├── inventivus/          ← the actual product. Everything below this line is here.
├── memory/PRD.md        Original product requirements and backlog
├── backend/             Emergent scaffold (FastAPI "Hello World" + Mongo) — unused
├── frontend/            Emergent scaffold (CRA + shadcn/ui starter)      — unused
├── tests/               Empty pytest package left by the scaffold
└── test_result.md       Scaffold testing-protocol file

backend/, frontend/, and tests/ are leftovers from the project generator. They
are not wired into the desktop app and can be ignored (or deleted) — the Fastify
backend the app actually runs is inventivus/server/.


Quick start

Requires Node 20+ and Yarn 1.x.

cd inventivus
yarn install
yarn dev

yarn dev runs three things concurrently: the Vite dev server on :5173, a
TypeScript build of the Electron main + preload into dist-electron/, and Electron
itself — which spawns the Fastify backend on a free port.

Stack

Layer Tech
Shell Electron 43 (contextBridge IPC, no nodeIntegration)
Renderer React 18 · TypeScript · Vite 6 · Tailwind CSS
State Zustand (global) · TanStack Query (server)
Graph / canvas React Flow
Backend Fastify 5, spawned as a child process on launch
Storage SQLite via better-sqlite3 (WAL + FTS5 full-text search)
Version control isomorphic-git — real git repos per project
Collaboration Yjs + PartyKit (y-partykit)
Native interop koffi FFI for Win32 window tracking
AI Ollama · LM Studio · OpenAI-compatible · Anthropic
Payments Stripe Node SDK + Ed25519-signed licence tokens
Packaging electron-builder → Windows NSIS installer

What's in the app

  • Mission — dashboard and telemetry across projects.
  • Calculators — truss FEM, beam, buckling, and co-simulation, with sandboxed
    controller expressions and live charting.
  • Machines — visual architecture layout wired to simulation runs.
  • Integrations — register any executable (CAD tool, simulator, terminal),
    launch it, and park a frameless HUD window in front of it. The HUD is a genuine
    second window owned by the launched app, not a reparented overlay — see
    SETUP.md § "The HUD is not an overlay".
  • Version control — git plus entity-level history, mirrored to a workspace.
  • Athena — full-page chat and a floating dock, SSE-streamed from the local
    backend so API keys never reach the renderer.
  • Projects — CRUD, invites, join flow, status control, GitHub sign-in via
    device flow.
  • Global search — SQLite FTS5 behind a Ctrl/+K
    command palette.

Editions and the free/Pro split

Two builds ship from one codebase with a single branch taken:

  • Standard — free tier with feature gates (calculators, machines, HUD live help)
    and quantity caps (5 projects, 3 integrations).
  • Unlocked — same code, resolveEntitlement short-circuits to Pro.

Version control and collaboration are free on purpose: a lapsed subscription must
never appear to have eaten someone's work. Limits are enforced on creation only,
so a user who drops from Pro keeps everything they already have.

Pro is proved by an Ed25519-signed licence token minted by the issuer worker
after a Stripe webhook — never by a local database column. The app embeds only the
public key, so it can verify a licence but cannot mint one. Enforcement is
server-side: gated routes return 402 regardless of what the UI renders.


Building the installers

cd inventivus
yarn package:standard   # → release/standard/Inventivus-Setup-0.1.0.exe
yarn package:unlocked   # → release/unlocked/
yarn package:both       # build once, package twice
yarn package:dir        # unpacked build, faster for testing

Scripts reference

yarn dev                # Vite + Electron + live backend
yarn dev:unlocked       # same, with Pro entitlements
yarn build              # renderer + electron main + server
yarn lint               # tsc --noEmit && eslint
yarn start:server       # backend only, for debugging

yarn verify:editions    # assert standard/unlocked packages differ correctly
yarn verify:persistence # assert userData survives reinstall
yarn verify:webhooks    # sign synthetic Stripe events → SQLite
yarn verify:pathb       # polling-based subscription refresh
yarn verify:ai          # AI provider proxy round-trip

Unit tests are colocated as *.test.ts next to their subjects and run with Vitest
(vitest.config.ts).


Where data lives

Path Contents
<userData>/inventivus.db SQLite database (WAL)
<userData>/config.enc Stripe + AI credentials, AES-256-GCM
<userData>/.inventivus.key 32-byte key generated on first launch, 0600

<userData> is %APPDATA%/Inventivus/ on Windows,
~/Library/Application Support/Inventivus/ on macOS,
~/.config/Inventivus/ on Linux.


Further reading

Document Covers
inventivus/SETUP.md First-time setup, keys, HUD, licensing, pitfalls
inventivus/README.md Architecture and module-level reference
inventivus/issuer/README.md Deploying the licence issuer (~15 min)
memory/PRD.md Original requirements and backlog
FILE_OPERATIONS_FIX.md File open/save handling notes
VERIFICATION_CHECKLIST.md Manual pre-release checklist

License

Proprietary. © Inventivus. All rights reserved.

Inventivus 1.9.0

Choose a tag to compare

@Therealsboy8 Therealsboy8 released this 06 Sep 21:18
8fe0fd3

Inventivus

Engineering mission control — a local-first Windows desktop application for
engineering calculators, machine architectures, native app overlays, version
control, and a built-in AI assistant named Athena.

Inventivus is an Electron app. A React + TypeScript SPA runs in the renderer, a
Fastify + SQLite backend runs as a child process of the Electron main process, and
everything — projects, simulation history, git repos, encrypted credentials — stays
on the user's machine. There is no hosted application server.

Two small cloud pieces exist and are optional: a PartyKit room for real-time
collaboration, and a Cloudflare Worker licence issuer that signs Pro tokens
after a Stripe webhook. Neither holds project data.


Changelog

v1.9 — 6 September 2026

Bug fixes

Workspace creation

  • Fixed EasyEDA Pro .eprj (and .eprj2, .elib) files being rejected at workspace creation with "file type not supported". The extension whitelist in server/utils/path-safety.ts had drifted out of sync with the app catalog and was missing every EasyEDA format plus ~40 other catalog extensions (.kicad_pro, .fcstd, .prjpcb, .sldprt, and more). Added a regression test that enumerates the full catalog so this class of bug cannot silently reappear.

Onboarding

  • The AI setup step is now skippable. Users without Ollama or an API key can click "Skip for now" and configure AI later in Settings → AI Provider. The app opens normally in the meantime; document analysis returns a clear "no AI configured" message rather than failing silently.
  • Added a collapsible step-by-step setup guide per provider (install commands, model pull commands, exact URLs, port numbers) shown inline on the AI step.
  • Rewrote the "connection failed" advice into numbered, actionable troubleshooting steps for each provider.

Team / sharing

  • Free-tier project-share cap could be bypassed by using the bulk share path (POST /api/team/share/apply with no project_id). Fixed: bulk path now pre-counts and enforces the cap.
  • Task delete (DELETE /api/team/tasks/:id) had no authorisation — any team member could delete any task. Fixed: only the task creator or a team owner may delete.
  • POST /api/team/events?month= had no format validation; an unvalidated value was used as a SQL LIKE operand, returning all events. Fixed: reject anything not matching YYYY-MM.
  • Optional fields on events and tasks (description, time, assigned_to_member_id) were stored as empty strings instead of NULL, breaking IS NULL queries. Fixed to store NULL.
  • Task unassign was impossible — assigned_to_member_id only accepted a string, not null. Fixed: accepts z.string().nullable().
  • Post display-name fallback used the team name instead of member_id. Fixed.

Payments / Stripe

  • customer.subscription.deleted webhook cleared tier and status but left subscription_id set. Subsequent subscription refresh and portal calls would then attempt to operate on the deleted subscription, returning 402/404 from Stripe. Fixed: null out subscription_id on deletion.
  • Success page copy said "Pro subscription is active" for all plans, including Enterprise customers. Fixed to neutral wording.

Version control

  • Data loss: renaming a workspace then running a scoped commit silently dropped the renamed workspace's manifest entry (matched by name instead of stable repo_path), causing pruneOrphans to delete the file from the repository. Fixed: carry-forward matches by repo_path. Added a regression test.
  • POST /vcs/unstage returned a raw 500 stack trace when called on a file that was never committed to HEAD. Fixed: returns 400 with the git error message.
  • Commit error detection in VersionControl.tsx matched (e as Error).message.includes('409') — any error message containing "409" would show "Nothing to commit" instead of the real error. Fixed to e instanceof ApiError && e.status === 409.
  • stageAll() returned the count of all files with any status rather than files newly staged. Fixed.

Cross-domain checking (core feature)

  • disciplineOf returned 'other' for EDA, firmware, and CAD nodes not yet placed in a container, in three separate locations: drift.ts, consequence.ts, and inference.ts. This silently excluded real cross-discipline connections from drift reports, consequence assessments, and the inference brief sent to the AI model — the most critical output of the system. Fixed in all three with a detector-based fallback.
  • EasyEDA Pro document detector ID was hardcoded to 'easyeda-schematic' instead of 'document-projection', breaking the provenance chain for .eprj files in drift detection. Fixed.
  • Support-part warnings were emitted twice in EasyEDA Pro document detection (once in warnings, once via omitted). Fixed.
  • Detection warnings were concatenated twice into the machine-links response, doubling every warning shown to the user. Fixed.
  • partStates was not passed to computeStaleness in the /inference endpoint (unlike /staleness), so CAD parts from container documents were always shown as current to the AI model regardless of actual state. Fixed.
  • Inference test fixture DRIFT was missing required revised and consequences fields, causing tests to exercise the wrong struct shape. Fixed.

Repository layout

.
├── inventivus/          ← the actual product. Everything below this line is here.
├── memory/PRD.md        Original product requirements and backlog
├── backend/             Emergent scaffold (FastAPI "Hello World" + Mongo) — unused
├── frontend/            Emergent scaffold (CRA + shadcn/ui starter)      — unused
├── tests/               Empty pytest package left by the scaffold
└── test_result.md       Scaffold testing-protocol file

backend/, frontend/, and tests/ are leftovers from the project generator. They
are not wired into the desktop app and can be ignored (or deleted) — the Fastify
backend the app actually runs is inventivus/server/.


Quick start

Requires Node 20+ and Yarn 1.x.

cd inventivus
yarn install
yarn dev

yarn dev runs three things concurrently: the Vite dev server on :5173, a
TypeScript build of the Electron main + preload into dist-electron/, and Electron
itself — which spawns the Fastify backend on a free port.

First launch opens the onboarding wizard. To skip the paywall while developing:

yarn dev:unlocked

Full setup walkthrough, including where each Stripe key goes:
inventivus/SETUP.md.
Deeper reference on architecture and internals:
inventivus/README.md.


Stack

Layer Tech
Shell Electron 43 (contextBridge IPC, no nodeIntegration)
Renderer React 18 · TypeScript · Vite 6 · Tailwind CSS
State Zustand (global) · TanStack Query (server)
Graph / canvas React Flow
Backend Fastify 5, spawned as a child process on launch
Storage SQLite via better-sqlite3 (WAL + FTS5 full-text search)
Version control isomorphic-git — real git repos per project
Collaboration Yjs + PartyKit (y-partykit)
Native interop koffi FFI for Win32 window tracking
AI Ollama · LM Studio · OpenAI-compatible · Anthropic
Payments Stripe Node SDK + Ed25519-signed licence tokens
Packaging electron-builder → Windows NSIS installer

What's in the app

  • Mission — dashboard and telemetry across projects.
  • Calculators — truss FEM, beam, buckling, and co-simulation, with sandboxed
    controller expressions and live charting.
  • Machines — visual architecture layout wired to simulation runs.
  • Integrations — register any executable (CAD tool, simulator, terminal),
    launch it, and park a frameless HUD window in front of it. The HUD is a genuine
    second window owned by the launched app, not a reparented overlay — see
    SETUP.md § "The HUD is not an overlay".
  • Version control — git plus entity-level history, mirrored to a workspace.
  • Athena — full-page chat and a floating dock, SSE-streamed from the local
    backend so API keys never reach the renderer.
  • Projects — CRUD, invites, join flow, status control, GitHub sign-in via
    device flow.
  • Global search — SQLite FTS5 behind a Ctrl/+K
    command palette.

Editions and the free/Pro split

Two builds ship from one codebase with a single branch taken:

  • Standard — free tier with feature gates (calculators, machines, HUD live help)
    and quantity caps (5 projects, 3 integrations).
  • Unlocked — same code, resolveEntitlement short-circuits to Pro.

Version control and collaboration are free on purpose: a lapsed subscription must
never appear to have eaten someone's work. Limits are enforced on creation only,
so a user who drops from Pro keeps everything they already have.

Pro is proved by an Ed25519-signed licence token minted by the issuer worker
after a Stripe webhook — never by a local database column. The app embeds only the
public key, so it can verify a licence but cannot mint one. Enforcement is
server-side: gated routes return 402 regardless of what the UI renders.


Building the installers

cd inventivus
yarn package:standard   # → release/standard/Inventivus-Setup-0.1.0.exe
yarn p...
Read more