Bump package version to v0.1.0:93 (reminders + NL-query)

Ships the next s9pk for the box, which jumps from v91 and so bundles two
in-repo-but-undeployed workstreams:
  - W1 reminders & follow-ups (v92): in-app migration 0006 (additive — a new
    `reminders` table + indexes; verified up/down against a copy of crm.db).
  - W2 natural-language query: read-only POST /api/query/nl + /api/query/catalog
    (require_bot_or_admin, audited), local-model translation, no schema change.

The Matrix Q&A client for W2 ships separately on the Spark and depends on this
endpoint being live on the box.
This commit is contained in:
Keysat
2026-06-18 19:56:53 -05:00
parent 68106d7a5a
commit f7b03ee109
3 changed files with 28 additions and 4 deletions
+3 -2
View File
@@ -57,8 +57,9 @@ export const PACKAGE_TITLE = 'Ten31 Database'
// * 0.1.0:89 (email-proposal review over Matrix + a dedicated agent role: Email Capture's proposed grid notes gain a click-to-view inline popup of the source email [from/to/cc/date/subject/scrollable body, via the existing GET /api/email/detail]; and a CRM→Matrix review bridge — the intake bot [Spark] pulls pending proposals, posts a review card to a dedicated review room [MATRIX_EMAIL_REVIEW_ROOM], and relays in-thread yes/no/NL-edit back to the CRM, with web panel ↔ Matrix kept in sync [decide on either surface; the other reflects it]. New side table email_proposal_matrix [email-integration migration 0003, additive + idempotent] holds per-proposal Matrix thread state; new bot-or-admin endpoints GET /api/intake/email-proposals + .../{id}/matrix + .../{id}/decide, gated by a new 'bot' role [authenticated, never admin]. Bot poll loop + review-room handling ship on the Spark, not the s9pk)
// * 0.1.0:90 (give admins a UI path to provision the 'bot' role added in v89: the Settings → Admin edit-user role dropdown now offers "bot" alongside member/admin [the teammate-invite form stays member/admin only — provisioning an agent account is an admin re-classification, not an invite]; backend already accepted it; frontend-only, no schema change)
// * 0.1.0:91 (clarify email-proposal note wording: the proposed grid note now NAMES who emailed whom — "{teammate} emailed {investor}" outbound / "{sender} emailed the team" inbound — instead of a bare "Sent"/"Received"; also fixes a misclassification where a sender on our corporate domain whose mailbox isn't enrolled read as "Received" [outbound now also matches our domain, public providers like gmail excluded so an LP's gmail never reads as ours]; going-forward only, no schema change. Matrix-side review tweaks — dash separators + redacting decided cards — ship on the Spark, not the s9pk)
// * Current: 0.1.0:92 (reminders & follow-ups, W1: new `reminders` table [in-app migration 0006; logical FK to fundraising_investors.id + denormalized name], full CRUD at /api/reminders [soft-delete; open/done/snoozed/cancelled; assignee; source human/bot/automation], read-only derived `reminder_status` grid column [overdue/due_soon/open — injected like pipeline_stage, filterable], orphan reconciler, Reminders page + Dashboard "Reminders Due" card + daily-digest "reminders due" section, and a per-investor last_activity_at recency rollup. Pure local CRM, no LLM path)
export const PACKAGE_VERSION = '0.1.0:92'
// * 0.1.0:92 (reminders & follow-ups, W1: new `reminders` table [in-app migration 0006; logical FK to fundraising_investors.id + denormalized name], full CRUD at /api/reminders [soft-delete; open/done/snoozed/cancelled; assignee; source human/bot/automation], read-only derived `reminder_status` grid column [overdue/due_soon/open — injected like pipeline_stage, filterable], orphan reconciler, Reminders page + Dashboard "Reminders Due" card + daily-digest "reminders due" section, and a per-investor last_activity_at recency rollup. Pure local CRM, no LLM path)
// * Current: 0.1.0:93 (natural-language query, W2: read-only "ask the database in plain English" — a curated, parameterized query catalog [backend/nl_query/] behind a strict slot validator [the trust boundary — no generic SQL / dynamic identifiers]; a local-Qwen translator maps a question→{intent,slots} via Spark Control so the question never leaves the box [no Claude, no redaction]; new endpoints POST /api/query/nl + GET /api/query/catalog [require_bot_or_admin, audited entity_type='nl_query'], results never returned to any model; no schema change. The Matrix Q&A client [dedicated room + ?/@bot trigger] ships on the Spark, not the s9pk)
export const PACKAGE_VERSION = '0.1.0:93'
export const DATA_MOUNT_PATH = '/data'
export const WEB_PORT = 8080
+3 -2
View File
@@ -53,8 +53,9 @@ import { v_0_1_0_89 } from './v0.1.0.89'
import { v_0_1_0_90 } from './v0.1.0.90'
import { v_0_1_0_91 } from './v0.1.0.91'
import { v_0_1_0_92 } from './v0.1.0.92'
import { v_0_1_0_93 } from './v0.1.0.93'
export const versionGraph = VersionGraph.of({
current: v_0_1_0_92,
other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51, v_0_1_0_52, v_0_1_0_53, v_0_1_0_54, v_0_1_0_55, v_0_1_0_56, v_0_1_0_57, v_0_1_0_58, v_0_1_0_59, v_0_1_0_60, v_0_1_0_61, v_0_1_0_62, v_0_1_0_63, v_0_1_0_64, v_0_1_0_65, v_0_1_0_66, v_0_1_0_67, v_0_1_0_68, v_0_1_0_69, v_0_1_0_70, v_0_1_0_71, v_0_1_0_72, v_0_1_0_73, v_0_1_0_74, v_0_1_0_75, v_0_1_0_76, v_0_1_0_77, v_0_1_0_78, v_0_1_0_79, v_0_1_0_80, v_0_1_0_81, v_0_1_0_82, v_0_1_0_83, v_0_1_0_84, v_0_1_0_85, v_0_1_0_86, v_0_1_0_87, v_0_1_0_88, v_0_1_0_89, v_0_1_0_90, v_0_1_0_91],
current: v_0_1_0_93,
other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51, v_0_1_0_52, v_0_1_0_53, v_0_1_0_54, v_0_1_0_55, v_0_1_0_56, v_0_1_0_57, v_0_1_0_58, v_0_1_0_59, v_0_1_0_60, v_0_1_0_61, v_0_1_0_62, v_0_1_0_63, v_0_1_0_64, v_0_1_0_65, v_0_1_0_66, v_0_1_0_67, v_0_1_0_68, v_0_1_0_69, v_0_1_0_70, v_0_1_0_71, v_0_1_0_72, v_0_1_0_73, v_0_1_0_74, v_0_1_0_75, v_0_1_0_76, v_0_1_0_77, v_0_1_0_78, v_0_1_0_79, v_0_1_0_80, v_0_1_0_81, v_0_1_0_82, v_0_1_0_83, v_0_1_0_84, v_0_1_0_85, v_0_1_0_86, v_0_1_0_87, v_0_1_0_88, v_0_1_0_89, v_0_1_0_90, v_0_1_0_91, v_0_1_0_92],
})
+22
View File
@@ -0,0 +1,22 @@
import { VersionInfo } from '@start9labs/start-sdk'
// Natural-language query (W2) — read-only "ask the database in plain English". A curated,
// parameterized query catalog (backend/nl_query/) sits behind a strict slot validator that is
// the trust boundary: a caller (or the local model) supplies only typed slot VALUES, never a
// table/column, an operator, or SQL. A local-Qwen translator maps a question -> {intent, slots}
// via Spark Control, so the question never leaves the box (no Claude, no redaction); results
// never go back to any model. New endpoints POST /api/query/nl + GET /api/query/catalog
// (require_bot_or_admin, audited as entity_type='nl_query'). No schema change — read-only — so
// up/down are no-ops. The Matrix Q&A client (a dedicated room + the ?/@bot trigger) ships
// separately on the Spark, not in this s9pk.
export const v_0_1_0_93 = VersionInfo.of({
version: '0.1.0:93',
releaseNotes: {
en_US: [
'Natural-language query (read-only): ask the fundraising database in plain English from',
'the Matrix Q&A room — translated on-box by the local model (nothing leaves the box),',
'answering only curated, parameterized queries.',
].join(' '),
},
migrations: { up: async () => {}, down: async () => {} },
})