From 7fc78d7058e375273d97beb80553fa3691cea76f Mon Sep 17 00:00:00 2001 From: Jonathan Kirkwood Date: Wed, 1 Jul 2026 13:39:56 -0500 Subject: [PATCH] Release 0.2.21; track the StartOS version files Cut version 0.2.21 (current = v_0_2_21) with the adjudicated DO-item fixes. Also commits the previously-untracked v_0_2_* version files that versions/index.ts imports (ROADMAP item D2), so a fresh checkout builds without dangling imports. The missing v_0_2_2 is intentional (versions are an unordered set). Built and verified: ten31portal_x86_64.s9pk packs cleanly at 0.2.21:0, arch x86_64, SDK 0.4.0. --- deploy/package.json | 2 +- deploy/startos/install/versions/index.ts | 25 +++++++++++++++++++-- deploy/startos/install/versions/v_0_2_0.ts | 16 +++++++++++++ deploy/startos/install/versions/v_0_2_1.ts | 15 +++++++++++++ deploy/startos/install/versions/v_0_2_10.ts | 14 ++++++++++++ deploy/startos/install/versions/v_0_2_11.ts | 14 ++++++++++++ deploy/startos/install/versions/v_0_2_12.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_13.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_14.ts | 14 ++++++++++++ deploy/startos/install/versions/v_0_2_15.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_16.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_17.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_18.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_19.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_20.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_21.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_3.ts | 14 ++++++++++++ deploy/startos/install/versions/v_0_2_4.ts | 14 ++++++++++++ deploy/startos/install/versions/v_0_2_5.ts | 14 ++++++++++++ deploy/startos/install/versions/v_0_2_6.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_7.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_8.ts | 13 +++++++++++ deploy/startos/install/versions/v_0_2_9.ts | 13 +++++++++++ 23 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 deploy/startos/install/versions/v_0_2_0.ts create mode 100644 deploy/startos/install/versions/v_0_2_1.ts create mode 100644 deploy/startos/install/versions/v_0_2_10.ts create mode 100644 deploy/startos/install/versions/v_0_2_11.ts create mode 100644 deploy/startos/install/versions/v_0_2_12.ts create mode 100644 deploy/startos/install/versions/v_0_2_13.ts create mode 100644 deploy/startos/install/versions/v_0_2_14.ts create mode 100644 deploy/startos/install/versions/v_0_2_15.ts create mode 100644 deploy/startos/install/versions/v_0_2_16.ts create mode 100644 deploy/startos/install/versions/v_0_2_17.ts create mode 100644 deploy/startos/install/versions/v_0_2_18.ts create mode 100644 deploy/startos/install/versions/v_0_2_19.ts create mode 100644 deploy/startos/install/versions/v_0_2_20.ts create mode 100644 deploy/startos/install/versions/v_0_2_21.ts create mode 100644 deploy/startos/install/versions/v_0_2_3.ts create mode 100644 deploy/startos/install/versions/v_0_2_4.ts create mode 100644 deploy/startos/install/versions/v_0_2_5.ts create mode 100644 deploy/startos/install/versions/v_0_2_6.ts create mode 100644 deploy/startos/install/versions/v_0_2_7.ts create mode 100644 deploy/startos/install/versions/v_0_2_8.ts create mode 100644 deploy/startos/install/versions/v_0_2_9.ts diff --git a/deploy/package.json b/deploy/package.json index 804ecee..886dbfe 100644 --- a/deploy/package.json +++ b/deploy/package.json @@ -1,6 +1,6 @@ { "name": "ten31portal-startos", - "version": "0.2.20", + "version": "0.2.21", "private": true, "scripts": { "build": "npm run check && rm -rf ./javascript && ncc build startos/index.ts -o ./javascript", diff --git a/deploy/startos/install/versions/index.ts b/deploy/startos/install/versions/index.ts index 2dbbcfb..4059bcf 100644 --- a/deploy/startos/install/versions/index.ts +++ b/deploy/startos/install/versions/index.ts @@ -1,2 +1,23 @@ -export { v_0_1_0 as current } from './v_0_1_0' -export const other = [] +export { v_0_2_21 as current } from './v_0_2_21' +import { v_0_1_0 } from './v_0_1_0' +import { v_0_2_0 } from './v_0_2_0' +import { v_0_2_1 } from './v_0_2_1' +import { v_0_2_3 } from './v_0_2_3' +import { v_0_2_4 } from './v_0_2_4' +import { v_0_2_5 } from './v_0_2_5' +import { v_0_2_6 } from './v_0_2_6' +import { v_0_2_7 } from './v_0_2_7' +import { v_0_2_8 } from './v_0_2_8' +import { v_0_2_9 } from './v_0_2_9' +import { v_0_2_10 } from './v_0_2_10' +import { v_0_2_11 } from './v_0_2_11' +import { v_0_2_12 } from './v_0_2_12' +import { v_0_2_13 } from './v_0_2_13' +import { v_0_2_14 } from './v_0_2_14' +import { v_0_2_15 } from './v_0_2_15' +import { v_0_2_16 } from './v_0_2_16' +import { v_0_2_17 } from './v_0_2_17' +import { v_0_2_18 } from './v_0_2_18' +import { v_0_2_19 } from './v_0_2_19' +import { v_0_2_20 } from './v_0_2_20' +export const other = [v_0_1_0, v_0_2_0, v_0_2_1, v_0_2_3, v_0_2_4, v_0_2_5, v_0_2_6, v_0_2_7, v_0_2_8, v_0_2_9, v_0_2_10, v_0_2_11, v_0_2_12, v_0_2_13, v_0_2_14, v_0_2_15, v_0_2_16, v_0_2_17, v_0_2_18, v_0_2_19, v_0_2_20] diff --git a/deploy/startos/install/versions/v_0_2_0.ts b/deploy/startos/install/versions/v_0_2_0.ts new file mode 100644 index 0000000..7fb251c --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_0.ts @@ -0,0 +1,16 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_0 = VersionInfo.of({ + version: '0.2.0:0', + releaseNotes: { + en_US: + 'Investor and fund-administrator accounts. Per-entity access control, built-in document storage (statements, K-1s), and per-investor capital-account statements. Admin screens to create accounts, grant entity access, upload documents, and enter capital-account figures.', + }, + migrations: { + // New tables (entity_access, documents, capital_account_statements) and the + // users.username column are applied by Alembic on app startup. No StartOS-level + // data migration is required. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_1.ts b/deploy/startos/install/versions/v_0_2_1.ts new file mode 100644 index 0000000..d7a38d4 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_1.ts @@ -0,0 +1,15 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_1 = VersionInfo.of({ + version: '0.2.1:0', + releaseNotes: { + en_US: + 'Owner access grid (accounts by fund/SPV, click to grant or revoke access) and a capital-account importer that reads a fund-administrator spreadsheet, matches or creates investor accounts on review, grants entity access, and loads each investor\'s capital-account balance.', + }, + migrations: { + // No schema changes beyond 0.2.0; new features reuse existing tables. Alembic + // remains the source of truth for the database schema on app startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_10.ts b/deploy/startos/install/versions/v_0_2_10.ts new file mode 100644 index 0000000..4b1386d --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_10.ts @@ -0,0 +1,14 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_10 = VersionInfo.of({ + version: '0.2.10:0', + releaseNotes: { + en_US: + 'One unified Import: a single eNAV upload loads fund holdings/NAV and members + capital (commitment, paid-in, distributions, current value). Investor view now shows commitment and DPI alongside current value. Menu cleanup: one Import item, Audit Log moved to the bottom.', + }, + migrations: { + // Adds capital_account_statements.commitment_cents; applied by Alembic on startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_11.ts b/deploy/startos/install/versions/v_0_2_11.ts new file mode 100644 index 0000000..8d21642 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_11.ts @@ -0,0 +1,14 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_11 = VersionInfo.of({ + version: '0.2.11:0', + releaseNotes: { + en_US: + 'Linked investor logins: an investor who invests under several names (e.g. an IRA and a trust, or through different Partners) can be given one sign-on that shows every name\'s investments together, labeled by name. Set it in Users → Manage → Login. Also: sortable columns on the Entities view.', + }, + migrations: { + // Adds users.primary_account_id; applied by Alembic on startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_12.ts b/deploy/startos/install/versions/v_0_2_12.ts new file mode 100644 index 0000000..9354642 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_12.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_12 = VersionInfo.of({ + version: '0.2.12:0', + releaseNotes: { + en_US: + 'Clearnet performance: gzip compression on all responses (the ~320KB app bundle drops to ~90KB over the wire) and long-lived browser caching of content-hashed assets, so repeat visits are near-instant. No data changes.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_13.ts b/deploy/startos/install/versions/v_0_2_13.ts new file mode 100644 index 0000000..b38ca7c --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_13.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_13 = VersionInfo.of({ + version: '0.2.13:0', + releaseNotes: { + en_US: + 'Re-importing a NAV now updates that quarter in place instead of adding a second round (no more doubled totals on the Entities view). New Ten31 Portal branding and logo.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_14.ts b/deploy/startos/install/versions/v_0_2_14.ts new file mode 100644 index 0000000..bc8c87e --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_14.ts @@ -0,0 +1,14 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_14 = VersionInfo.of({ + version: '0.2.14:0', + releaseNotes: { + en_US: + 'User administration from StartOS Actions: Create User, Reset Password, List Users, and Delete User. New role layout — Managing Partner (full access incl. sign-off), Operations (full access except sign-off), Fund Admin. The built-in Service Admin can be reset but never deleted.', + }, + migrations: { + // Adds users.is_service_admin and flags the bootstrap admin; applied by Alembic on startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_15.ts b/deploy/startos/install/versions/v_0_2_15.ts new file mode 100644 index 0000000..2919927 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_15.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_15 = VersionInfo.of({ + version: '0.2.15:0', + releaseNotes: { + en_US: + 'Fixes doubled "Invested" totals by removing duplicate holdings/positions left by older imports (runs automatically on the next import of a fund, or all at once via the new "Fix Duplicate Holdings" action). Usernames are now editable in Users → Manage. Mobile/PWA: installable to a phone home screen with an app icon, plus a responsive layout with a collapsible menu.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_16.ts b/deploy/startos/install/versions/v_0_2_16.ts new file mode 100644 index 0000000..36ab199 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_16.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_16 = VersionInfo.of({ + version: '0.2.16:0', + releaseNotes: { + en_US: + 'Clear and rebuild a fund: re-import with the new "Replace existing holdings" option to wipe a fund\'s old positions and rebuild from the file — for when a source change (e.g. Carta → eNAV) renamed every position. Also available as the "Reset Fund Holdings" and "List Funds" actions. Investor capital accounts are never affected.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_17.ts b/deploy/startos/install/versions/v_0_2_17.ts new file mode 100644 index 0000000..316ae30 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_17.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_17 = VersionInfo.of({ + version: '0.2.17:0', + releaseNotes: { + en_US: + 'The Entities view now shows a Committed column (total LP commitments to each fund) alongside Invested (capital deployed into companies) and Last Signed Value.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_18.ts b/deploy/startos/install/versions/v_0_2_18.ts new file mode 100644 index 0000000..64e39e3 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_18.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_18 = VersionInfo.of({ + version: '0.2.18:0', + releaseNotes: { + en_US: + 'The fund Partners tab now shows each member\'s Committed, Paid-in, and Distributions alongside their capital value, with a total committed for the fund — matching what investors see in their own portal.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_19.ts b/deploy/startos/install/versions/v_0_2_19.ts new file mode 100644 index 0000000..034739c --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_19.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_19 = VersionInfo.of({ + version: '0.2.19:0', + releaseNotes: { + en_US: + 'Mobile/PWA fixes: the top bar (including Sign out) no longer hides behind the phone status bar, and the Entities view now shows each fund as a card that fits the screen — no more zooming out or sideways scrolling.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_20.ts b/deploy/startos/install/versions/v_0_2_20.ts new file mode 100644 index 0000000..fb493fc --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_20.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_20 = VersionInfo.of({ + version: '0.2.20:0', + releaseNotes: { + en_US: + 'Passwords now persist when you edit an investor (the password only changes if you type a new one). Investors can change their own password from the portal, and admins keep the ability to reset it. Every password field has a show/hide eye toggle.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_21.ts b/deploy/startos/install/versions/v_0_2_21.ts new file mode 100644 index 0000000..5d4de49 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_21.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_21 = VersionInfo.of({ + version: '0.2.21:0', + releaseNotes: { + en_US: + 'Importing with replace-existing-holdings now asks for confirmation before clearing a fund, and shows step-by-step progress. You can expand an audit log entry to see its full detail. Entities with no investments show a clear empty state. A brief server hiccup shows a retry prompt instead of logging you out. Backend adds document upload size limits, database indexes, and an automated test suite.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_3.ts b/deploy/startos/install/versions/v_0_2_3.ts new file mode 100644 index 0000000..8e27397 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_3.ts @@ -0,0 +1,14 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_3 = VersionInfo.of({ + version: '0.2.3:0', + releaseNotes: { + en_US: + 'Replace the Carta importer with a fund-administrator eNAV importer. Reads the holdings (HLD) sheet into holdings, positions, and a quarter valuation; decrypts password-protected workbooks (password entered on upload); reads the report date from the sheet; accepts XLSX or CSV.', + }, + migrations: { + // No schema changes; import is parsing-only. Alembic owns the DB schema on startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_4.ts b/deploy/startos/install/versions/v_0_2_4.ts new file mode 100644 index 0000000..23e7e2a --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_4.ts @@ -0,0 +1,14 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_4 = VersionInfo.of({ + version: '0.2.4:0', + releaseNotes: { + en_US: + 'Import fund members from the eNAV ALLOC SI tab. The capital-account import now reads the investor roster, matches existing members by fund-administrator investor ID (idempotent re-imports), offers to create new members (without a login until you set a password), grants entity access, and loads each member\'s capital balance.', + }, + migrations: { + // Adds users.external_investor_id; applied by Alembic on startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_5.ts b/deploy/startos/install/versions/v_0_2_5.ts new file mode 100644 index 0000000..48d7d42 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_5.ts @@ -0,0 +1,14 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_5 = VersionInfo.of({ + version: '0.2.5:0', + releaseNotes: { + en_US: + 'Fund page Partners and Documents tabs. Partners lists each member with their investor ID, login status (members imported without a password show "No login yet" until you set one), and latest capital value. Documents shows all of the fund\'s files for admins.', + }, + migrations: { + // Adds users.login_enabled; applied by Alembic on startup. + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_6.ts b/deploy/startos/install/versions/v_0_2_6.ts new file mode 100644 index 0000000..91b8a63 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_6.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_6 = VersionInfo.of({ + version: '0.2.6:0', + releaseNotes: { + en_US: + 'Fund page Partners and Documents tabs: Partners lists each member with investor ID, login status (members imported without a password show "No login yet"), and latest capital value; Documents shows all of the fund\'s files for admins.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_7.ts b/deploy/startos/install/versions/v_0_2_7.ts new file mode 100644 index 0000000..b387b88 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_7.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_7 = VersionInfo.of({ + version: '0.2.7:0', + releaseNotes: { + en_US: + 'Fund page Partners and Documents tabs (each partner with their capital value in the fund), plus a sidebar header alignment fix so the top-left borders meet cleanly.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_8.ts b/deploy/startos/install/versions/v_0_2_8.ts new file mode 100644 index 0000000..c8f0eed --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_8.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_8 = VersionInfo.of({ + version: '0.2.8:0', + releaseNotes: { + en_US: + 'Serve the web app with no-cache on index.html so upgrades show up immediately without a manual browser refresh. Includes the fund Partners/Documents tabs and the sidebar header alignment fix.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +}) diff --git a/deploy/startos/install/versions/v_0_2_9.ts b/deploy/startos/install/versions/v_0_2_9.ts new file mode 100644 index 0000000..33dc7b7 --- /dev/null +++ b/deploy/startos/install/versions/v_0_2_9.ts @@ -0,0 +1,13 @@ +import { VersionInfo } from '@start9labs/start-sdk' + +export const v_0_2_9 = VersionInfo.of({ + version: '0.2.9:0', + releaseNotes: { + en_US: + 'Show the running app version in the UI (sidebar / portal header) so updates are verifiable at a glance. Includes the fund Partners/Documents tabs, sidebar alignment fix, and no-cache on the web app.', + }, + migrations: { + up: async ({ effects }) => {}, + down: async ({ effects }) => {}, + }, +})