@promptowl/contextnest-community 1.25.0 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +102 -9
- package/CONFIGURATION.md +604 -117
- package/README.md +3 -2
- package/dist/{chunk-JDAOA5KP.js → chunk-H3W72HN3.js} +67 -14
- package/dist/{chunk-2KHM5C7V.js → chunk-MB52DWWP.js} +13 -15
- package/dist/{chunk-TI7HMP64.js → chunk-NFFUZF2B.js} +23 -2
- package/dist/{chunk-F66VCBLA.js → chunk-O3JEI33N.js} +51 -2
- package/dist/{chunk-7FROMOZM.js → chunk-QMQDWRHN.js} +180 -550
- package/dist/chunk-RXCVXG34.js +523 -0
- package/dist/{chunk-32SZCH36.js → chunk-SE5U4J4T.js} +4 -4
- package/dist/{chunk-KPGNZLZL.js → chunk-VHEMGQ3I.js} +1 -1
- package/dist/{chunk-DTLMBF4W.js → chunk-VRLAP4HB.js} +42 -17
- package/dist/{engine-TER6FDBP.js → engine-HLYQLP5T.js} +3 -2
- package/dist/{external-edit-service-CAGENHDJ.js → external-edit-service-3DFQ4EZZ.js} +4 -3
- package/dist/{grants-service-2OTFS7EH.js → grants-service-WICV4Y2J.js} +2 -2
- package/dist/index.js +1669 -521
- package/dist/invited-user-XEBX6BM4.js +12 -0
- package/dist/{migrations.postgres-23VJJJJX.js → migrations.postgres-HGSQ7IA5.js} +4 -0
- package/dist/{review-service-4G2XUFS6.js → review-service-GB43UQVH.js} +7 -6
- package/dist/{stewardship-service-S22V2JKG.js → stewardship-service-KDBPWRZI.js} +4 -3
- package/dist/{version-service-X4FAG2OZ.js → version-service-JYHFPSYP.js} +8 -3
- package/dist/web3/assets/ActivityTracePage-CkRoyIc-.js +1 -0
- package/dist/web3/assets/AgentDocsPage-BTRXmliv.js +1 -0
- package/dist/web3/assets/CollaboratorManager-CqJIkvs-.js +1 -0
- package/dist/web3/assets/CollaboratorsTab-JcO1P-qm.js +1 -0
- package/dist/web3/assets/DocumentEditor-D1GLeeEP.js +36 -0
- package/dist/web3/assets/DocumentsTab-BAgSxTX1.js +6 -0
- package/dist/web3/assets/ExternalEditsTab-DuuTXZap.js +1 -0
- package/dist/web3/assets/{MarkdownEditor-Dfk5uIE5.js → MarkdownEditor-BELFww9q.js} +130 -135
- package/dist/web3/assets/MarkdownEditor-ndtIx5x0.css +1 -0
- package/dist/web3/assets/NestPageHeader-Bbje2ncY.js +1 -0
- package/dist/web3/assets/NestView-D4OMXPQ7.js +73 -0
- package/dist/web3/assets/OverviewTab-FIDGjR3Q.js +6 -0
- package/dist/web3/assets/PersonCombobox-D52m_jhc.js +1 -0
- package/dist/web3/assets/{ReviewActions-BXDTDPp1.js → ReviewActions-DYqBcWlv.js} +2 -2
- package/dist/web3/assets/ReviewTab-DoxfygOb.js +1 -0
- package/dist/web3/assets/StewardsTab-CFsYjbEn.js +1 -0
- package/dist/web3/assets/SubmitForReviewModal-AW2OLNAE.js +1 -0
- package/dist/web3/assets/{alert-dialog-4SiLKlz8.js → alert-dialog-p-fBLSWx.js} +2 -2
- package/dist/web3/assets/{arrow-left-BAgIocLn.js → arrow-left-CiErCCTG.js} +1 -1
- package/dist/web3/assets/backlinks-DaVSYvhV.js +19 -0
- package/dist/web3/assets/boxes-VWrCCMzW.js +6 -0
- package/dist/web3/assets/{chevron-left-XR4ReJ9Z.js → chevron-left-CsD8gZwL.js} +1 -1
- package/dist/web3/assets/{circle-check-CSkZUEFK.js → circle-check-BBCXd9LI.js} +1 -1
- package/dist/web3/assets/{circle-x-in2o3aHU.js → circle-x-C9LsnORQ.js} +1 -1
- package/dist/web3/assets/{code-xml-pPQgdctI.js → code-xml-BaoV7HiQ.js} +1 -1
- package/dist/web3/assets/{corner-down-right-CuxZWscX.js → corner-down-right-DgiTXrtw.js} +1 -1
- package/dist/web3/assets/count-skeleton-CnEE4uF-.js +1 -0
- package/dist/web3/assets/{earth-CXOcThqn.js → earth-BmMbVt9k.js} +1 -1
- package/dist/web3/assets/{file-exclamation-point-CSphs1VD.js → file-exclamation-point-qJeca9-A.js} +1 -1
- package/dist/web3/assets/{folder-input-BAwK9tFL.js → folder-input-D7R93LJ6.js} +1 -1
- package/dist/web3/assets/index-DNmWTxN7.css +1 -0
- package/dist/web3/assets/index-DvuUIUP6.js +451 -0
- package/dist/web3/assets/{page-CUjuSs5Q.js → page-BJQuaTRW.js} +3 -3
- package/dist/web3/assets/page-Bb8xGOPQ.js +2 -0
- package/dist/web3/assets/page-BtM-qDzr.js +6 -0
- package/dist/web3/assets/page-Bxd0EG25.js +1 -0
- package/dist/web3/assets/page-C3QCO6IR.js +1 -0
- package/dist/web3/assets/page-CfoR0khy.js +6 -0
- package/dist/web3/assets/page-D7Zr5tAI.js +1 -0
- package/dist/web3/assets/page-DATSlHCW.js +6 -0
- package/dist/web3/assets/page-DTjPQizZ.js +45 -0
- package/dist/web3/assets/page-DspptlWr.js +1 -0
- package/dist/web3/assets/{page-xzYqkBUP.js → page-I6vAFJOj.js} +5 -5
- package/dist/web3/assets/page-QxI4Ud2s.js +9 -0
- package/dist/web3/assets/page-YcNNg-dX.js +1 -0
- package/dist/web3/assets/page-kM7eO5Kj.js +1 -0
- package/dist/web3/assets/{page-title-BkqlUA0j.js → page-title-Dn5jANiU.js} +1 -1
- package/dist/web3/assets/{play-B8xE9j5f.js → play-B2k_Ix-L.js} +1 -1
- package/dist/web3/assets/{send-CvAgOUPG.js → send-DPNxv3As.js} +1 -1
- package/dist/web3/assets/{settings-EY4A_DYv.js → settings-DZjq-OQA.js} +1 -1
- package/dist/web3/assets/{share-2-vGmZUl90.js → share-2-C-OnE2ru.js} +1 -1
- package/dist/web3/assets/{tag-Br_y1f00.js → tag-CwJl7FdI.js} +1 -1
- package/dist/web3/assets/{trash-2-B4hRXo-p.js → trash-2-aljmIff4.js} +1 -1
- package/dist/web3/assets/{user-plus-4CTYEkd3.js → user-plus-DPerZexX.js} +1 -1
- package/dist/web3/assets/{zap-BcsKR0ef.js → zap-CHZtiN7P.js} +1 -1
- package/dist/web3/index.html +2 -2
- package/package.json +8 -3
- package/dist/client-D44ZHDTJ.js +0 -11
- package/dist/keys-CTOGAG3W.js +0 -20
- package/dist/web3/assets/ActivityTracePage-D2iIbEph.js +0 -1
- package/dist/web3/assets/AgentDocsPage-Dkhgb1hk.js +0 -1
- package/dist/web3/assets/CollaboratorManager-Bo81D--Q.js +0 -1
- package/dist/web3/assets/CollaboratorsTab-DRCitQuX.js +0 -1
- package/dist/web3/assets/DocumentEditor-DV2WHYbj.js +0 -36
- package/dist/web3/assets/DocumentsTab-BUxBCN8o.js +0 -6
- package/dist/web3/assets/ExternalEditsTab-kIBimZyE.js +0 -1
- package/dist/web3/assets/MarkdownEditor-CsVusP2d.css +0 -1
- package/dist/web3/assets/NestPageHeader-yOK-OIYZ.js +0 -1
- package/dist/web3/assets/NestView-DwIagxwJ.js +0 -68
- package/dist/web3/assets/OverviewTab-DFOFMVyE.js +0 -1
- package/dist/web3/assets/PersonCombobox-D350WlrJ.js +0 -1
- package/dist/web3/assets/ReasonDialog-CN3ECAnQ.js +0 -1
- package/dist/web3/assets/ReviewTab-CZewAYiz.js +0 -1
- package/dist/web3/assets/StewardsTab-AagNWcWS.js +0 -1
- package/dist/web3/assets/SubmitForReviewModal-BOZJxwRN.js +0 -1
- package/dist/web3/assets/backlinks-Cb8Uf8mw.js +0 -24
- package/dist/web3/assets/card-UDyMRcps.js +0 -1
- package/dist/web3/assets/count-skeleton-DBWCDhRy.js +0 -1
- package/dist/web3/assets/dates-BCxbm4_q.js +0 -1
- package/dist/web3/assets/index-A0_ymcqL.js +0 -29
- package/dist/web3/assets/index-B5hLclEq.js +0 -389
- package/dist/web3/assets/index-DrUAtoQM.css +0 -1
- package/dist/web3/assets/page-BHD4beun.js +0 -1
- package/dist/web3/assets/page-BSYUXYmO.js +0 -11
- package/dist/web3/assets/page-BYc2DIux.js +0 -45
- package/dist/web3/assets/page-BfibLg8e.js +0 -1
- package/dist/web3/assets/page-CGe8MtUu.js +0 -9
- package/dist/web3/assets/page-CIgPJmG6.js +0 -2
- package/dist/web3/assets/page-Ck31nx9b.js +0 -1
- package/dist/web3/assets/page-Cpdj_11Y.js +0 -1
- package/dist/web3/assets/page-D0sN3GO6.js +0 -1
- package/dist/web3/assets/page-DEpH91X2.js +0 -1
- package/dist/web3/assets/page-l8-B7CGt.js +0 -1
- package/dist/web3/assets/page-mnSHmk6A.js +0 -6
- package/dist/web3/assets/refresh-cw-CsCtmWwX.js +0 -6
- package/dist/web3/assets/scroll-area-CbcH6yrZ.js +0 -1
- package/dist/web3/assets/scroll-area-dRWncRqa.css +0 -1
- package/dist/web3/assets/select-DrL0mpRN.js +0 -6
- package/dist/web3/assets/triangle-alert-CsYGyfGZ.js +0 -6
- package/dist/web3/assets/x-qxt1WrUi.js +0 -6
package/README.md
CHANGED
|
@@ -150,7 +150,7 @@ Keys are minted in the app (Workspace → API keys, or the Connect dialog) — o
|
|
|
150
150
|
| Activity trace — every governance action, per nest and server-wide | ✅ | ✅ |
|
|
151
151
|
| Notifications — Slack, Microsoft Teams, email | ✅ | ✅ |
|
|
152
152
|
| Centralized multi-tenant admin console | — | ✅ |
|
|
153
|
-
| Single sign-on (OIDC — Entra ID, Google, Okta, Keycloak) | ✅ | ✅ |
|
|
153
|
+
| Single sign-on (OIDC — Entra ID, Google, Okta, Keycloak) — [admin guide](./CONFIGURATION.md#single-sign-on-oidc) | ✅ | ✅ |
|
|
154
154
|
| SAML / SCIM provisioning | — | ✅ |
|
|
155
155
|
| Audit log streaming | — | ✅ |
|
|
156
156
|
| Policy transforms (redaction, summarization) | — | ✅ |
|
|
@@ -165,6 +165,7 @@ Release notes live in [CHANGELOG.md](./CHANGELOG.md).
|
|
|
165
165
|
## Documentation
|
|
166
166
|
|
|
167
167
|
- [CONFIGURATION.md](./CONFIGURATION.md) — every environment variable (port, auth mode, storage, notifications, telemetry)
|
|
168
|
+
- [Single sign-on admin guide](./CONFIGURATION.md#single-sign-on-oidc) — connect Microsoft Entra ID, Google, Okta, Keycloak or any OIDC provider; what happens to existing accounts, API keys and agents; every `sso_error` code with its fix
|
|
168
169
|
- [API.md](./API.md) — complete REST reference with request and response bodies
|
|
169
170
|
- [STEWARDSHIP.md](./STEWARDSHIP.md) — the governance model: modes, stewards, scopes, prime documents, teams, super-admins
|
|
170
171
|
- `<server>/llms.txt` — the agent manual the running server publishes; rendered as **Docs** in the app
|
|
@@ -217,4 +218,4 @@ The Software injects content into large language models. AI output may be inaccu
|
|
|
217
218
|
**Copyright © 2026 Promptowl LLC.** All rights reserved.
|
|
218
219
|
"ContextNest" and "PromptOwl" are trademarks of Promptowl LLC.
|
|
219
220
|
|
|
220
|
-
Promptowl LLC · 3060 Mercer University Dr Ste 110 · Atlanta, GA 30341 · USA
|
|
221
|
+
Promptowl LLC · 3060 Mercer University Dr Ste 110 · Atlanta, GA 30341 · USA
|
|
@@ -2,11 +2,6 @@ import {
|
|
|
2
2
|
ANON_USER_ID
|
|
3
3
|
} from "./chunk-YB3LKF7U.js";
|
|
4
4
|
|
|
5
|
-
// src/db/client.ts
|
|
6
|
-
import Database from "better-sqlite3";
|
|
7
|
-
import { mkdirSync, readFileSync } from "fs";
|
|
8
|
-
import { dirname as dirname2 } from "path";
|
|
9
|
-
|
|
10
5
|
// src/config.ts
|
|
11
6
|
import { join, dirname } from "path";
|
|
12
7
|
import { existsSync } from "fs";
|
|
@@ -356,6 +351,14 @@ var config = {
|
|
|
356
351
|
get PEOPLE_SUGGEST_ALL_USERS() {
|
|
357
352
|
return process.env.PEOPLE_SUGGEST_ALL_USERS === "true";
|
|
358
353
|
},
|
|
354
|
+
/**
|
|
355
|
+
* Who may create nests. "admins" (default): server admins only, until the
|
|
356
|
+
* server is on a paid plan. "everyone": any signed-in user. Open mode is
|
|
357
|
+
* unaffected (everyone is admin there).
|
|
358
|
+
*/
|
|
359
|
+
get NEST_CREATION() {
|
|
360
|
+
return process.env.NEST_CREATION?.trim().toLowerCase() === "everyone" ? "everyone" : "admins";
|
|
361
|
+
},
|
|
359
362
|
/**
|
|
360
363
|
* This server hosts several unrelated organizations (the PromptOwl-hosted
|
|
361
364
|
* deployment) rather than one company (a self-hosted install).
|
|
@@ -498,6 +501,34 @@ var config = {
|
|
|
498
501
|
get TYPE_TABLE_ENABLED() {
|
|
499
502
|
return process.env.TYPE_TABLE_ENABLED !== "false";
|
|
500
503
|
},
|
|
504
|
+
/**
|
|
505
|
+
* Hootie in the nest: the floating assistant on every page of the UI and
|
|
506
|
+
* its POST /nests/:id/chat route (default ON). Superadmin-editable at
|
|
507
|
+
* runtime via /admin/settings (hootie_enabled). Off → the route 404s and
|
|
508
|
+
* the launcher is hidden. Answering additionally needs the server-wide
|
|
509
|
+
* ANTHROPIC_API_KEY; without one the route answers 503, not 404 — the
|
|
510
|
+
* feature is on, it just isn't configured yet.
|
|
511
|
+
*/
|
|
512
|
+
get HOOTIE_ENABLED() {
|
|
513
|
+
return process.env.HOOTIE_ENABLED !== "false";
|
|
514
|
+
},
|
|
515
|
+
/** Model Hootie answers with. Superadmin-editable at runtime via
|
|
516
|
+
* /admin/settings (hootie_model). A gateway-side name (`ollama/…`,
|
|
517
|
+
* `gpt-…`) is fine when ANTHROPIC_BASE_URL points at one. */
|
|
518
|
+
get HOOTIE_MODEL() {
|
|
519
|
+
return process.env.HOOTIE_MODEL || "claude-opus-5";
|
|
520
|
+
},
|
|
521
|
+
/**
|
|
522
|
+
* Where the Anthropic-shaped model calls go. Empty = Anthropic directly.
|
|
523
|
+
* Set to a LiteLLM (or PromptOwl) gateway to route Hootie AND agent runs
|
|
524
|
+
* through it — one setting: the runner honours the same variable via the
|
|
525
|
+
* run bundle's env floor. Superadmin-editable (anthropic_base_url).
|
|
526
|
+
* Never a per-user vendor key: that is the shadow-AI hole the gateway
|
|
527
|
+
* exists to close.
|
|
528
|
+
*/
|
|
529
|
+
get ANTHROPIC_BASE_URL() {
|
|
530
|
+
return (process.env.ANTHROPIC_BASE_URL || "").trim().replace(/\/$/, "");
|
|
531
|
+
},
|
|
501
532
|
/**
|
|
502
533
|
* Sub-agent runs: lets a run spawn nested runs (an external runner calling
|
|
503
534
|
* back into POST /run for a child agent). Gated SEPARATELY from the base
|
|
@@ -553,6 +584,27 @@ var config = {
|
|
|
553
584
|
}
|
|
554
585
|
return raw;
|
|
555
586
|
},
|
|
587
|
+
/**
|
|
588
|
+
* Email transport: "smtp" (SMTP_URL, default) or "ses" (AWS SES via the SDK,
|
|
589
|
+
* for deployments that can't use SMTP). Anything else falls back to smtp.
|
|
590
|
+
*/
|
|
591
|
+
get EMAIL_PROVIDER() {
|
|
592
|
+
return process.env.EMAIL_PROVIDER?.trim().toLowerCase() === "ses" ? "ses" : "smtp";
|
|
593
|
+
},
|
|
594
|
+
/** AWS region for SES, e.g. us-east-1. Required when EMAIL_PROVIDER=ses. */
|
|
595
|
+
get SES_REGION() {
|
|
596
|
+
return process.env.SES_REGION?.trim() || null;
|
|
597
|
+
},
|
|
598
|
+
/**
|
|
599
|
+
* Optional static SES credentials. Both unset → the AWS default credential
|
|
600
|
+
* chain (IAM role, AWS_* env, shared profile). The secret is write-only.
|
|
601
|
+
*/
|
|
602
|
+
get SES_ACCESS_KEY_ID() {
|
|
603
|
+
return process.env.SES_ACCESS_KEY_ID?.trim() || null;
|
|
604
|
+
},
|
|
605
|
+
get SES_SECRET_ACCESS_KEY() {
|
|
606
|
+
return process.env.SES_SECRET_ACCESS_KEY?.trim() || null;
|
|
607
|
+
},
|
|
556
608
|
/**
|
|
557
609
|
* From address for notification emails. Shape-validated here (not only in
|
|
558
610
|
* the /admin/settings PATCH) so a value set directly via env/Docker can't
|
|
@@ -670,6 +722,11 @@ var config = {
|
|
|
670
722
|
}
|
|
671
723
|
};
|
|
672
724
|
|
|
725
|
+
// src/db/client.ts
|
|
726
|
+
import Database from "better-sqlite3";
|
|
727
|
+
import { mkdirSync, readFileSync } from "fs";
|
|
728
|
+
import { dirname as dirname2 } from "path";
|
|
729
|
+
|
|
673
730
|
// src/db/migrations.ts
|
|
674
731
|
function runMigrations(db) {
|
|
675
732
|
db.exec(`
|
|
@@ -867,6 +924,9 @@ function runMigrations(db) {
|
|
|
867
924
|
if (!nestCols.includes("reader_home_node")) {
|
|
868
925
|
db.exec("ALTER TABLE nests ADD COLUMN reader_home_node TEXT");
|
|
869
926
|
}
|
|
927
|
+
if (!nestCols.includes("branding_json")) {
|
|
928
|
+
db.exec("ALTER TABLE nests ADD COLUMN branding_json TEXT");
|
|
929
|
+
}
|
|
870
930
|
const userCols = db.prepare("PRAGMA table_info(users)").all().map((c) => c.name);
|
|
871
931
|
if (!userCols.includes("is_admin")) {
|
|
872
932
|
db.exec("ALTER TABLE users ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0");
|
|
@@ -2097,7 +2157,7 @@ async function initDb() {
|
|
|
2097
2157
|
if (config.DB_DRIVER === "postgres") {
|
|
2098
2158
|
const { Pool } = await import("pg");
|
|
2099
2159
|
const { PostgresAdapter } = await import("./adapter.postgres-6VZCMPQL.js");
|
|
2100
|
-
const { runPostgresMigrations } = await import("./migrations.postgres-
|
|
2160
|
+
const { runPostgresMigrations } = await import("./migrations.postgres-HGSQ7IA5.js");
|
|
2101
2161
|
const pool = new Pool(buildPgConfig());
|
|
2102
2162
|
adapter = new PostgresAdapter(pool);
|
|
2103
2163
|
await runPostgresMigrations(adapter);
|
|
@@ -2117,18 +2177,11 @@ function getDb() {
|
|
|
2117
2177
|
}
|
|
2118
2178
|
return adapter;
|
|
2119
2179
|
}
|
|
2120
|
-
async function resetDb() {
|
|
2121
|
-
if (adapter) {
|
|
2122
|
-
await adapter.close();
|
|
2123
|
-
adapter = null;
|
|
2124
|
-
}
|
|
2125
|
-
}
|
|
2126
2180
|
|
|
2127
2181
|
export {
|
|
2128
2182
|
isEmailish,
|
|
2129
2183
|
isEmailListish,
|
|
2130
2184
|
config,
|
|
2131
2185
|
initDb,
|
|
2132
|
-
getDb
|
|
2133
|
-
resetDb
|
|
2186
|
+
getDb
|
|
2134
2187
|
};
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildTitleMap,
|
|
3
|
-
canApproveWith,
|
|
4
|
-
canEditWith,
|
|
5
|
-
canViewWith,
|
|
6
|
-
collabPermToRole,
|
|
7
3
|
docLink,
|
|
8
4
|
isSuperAdmin,
|
|
9
5
|
nestAllowsSelfApprove,
|
|
10
6
|
nestName,
|
|
11
|
-
primaryRole,
|
|
12
7
|
resolveNestAccess,
|
|
13
8
|
resolveNestPermission,
|
|
14
|
-
resolveTeamRolesForUser
|
|
15
|
-
|
|
16
|
-
} from "./chunk-7FROMOZM.js";
|
|
9
|
+
resolveTeamRolesForUser
|
|
10
|
+
} from "./chunk-QMQDWRHN.js";
|
|
17
11
|
import {
|
|
18
12
|
ConflictError,
|
|
19
13
|
ValidationError
|
|
20
14
|
} from "./chunk-LHWOJPFE.js";
|
|
15
|
+
import {
|
|
16
|
+
canApproveWith,
|
|
17
|
+
canEditWith,
|
|
18
|
+
canViewWith,
|
|
19
|
+
collabPermToRole,
|
|
20
|
+
primaryRole,
|
|
21
|
+
sendEmailToRecipient
|
|
22
|
+
} from "./chunk-RXCVXG34.js";
|
|
21
23
|
import {
|
|
22
24
|
config,
|
|
23
25
|
getDb,
|
|
24
26
|
isEmailish
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-H3W72HN3.js";
|
|
26
28
|
|
|
27
29
|
// src/governance/stewardship-service.ts
|
|
28
30
|
import { v4 as uuid } from "uuid";
|
|
@@ -231,12 +233,8 @@ async function createStewardRecord(params) {
|
|
|
231
233
|
);
|
|
232
234
|
let userId = userRow?.id;
|
|
233
235
|
if (!userId) {
|
|
234
|
-
const {
|
|
235
|
-
userId =
|
|
236
|
-
await db.run(
|
|
237
|
-
"INSERT INTO users (id, email, name, password_hash, is_invited) VALUES (?, ?, ?, ?, 1)",
|
|
238
|
-
[userId, email, null, await hashPassword(uuid())]
|
|
239
|
-
);
|
|
236
|
+
const { findOrCreateInvitedUser } = await import("./invited-user-XEBX6BM4.js");
|
|
237
|
+
userId = (await findOrCreateInvitedUser(email)).id;
|
|
240
238
|
}
|
|
241
239
|
const created = await assignSteward({
|
|
242
240
|
nestId: params.nestId,
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
buildTitleMap,
|
|
3
3
|
insertOrReplace,
|
|
4
4
|
nowExpr
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QMQDWRHN.js";
|
|
6
6
|
import {
|
|
7
7
|
ValidationError
|
|
8
8
|
} from "./chunk-LHWOJPFE.js";
|
|
9
9
|
import {
|
|
10
10
|
getDb
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-H3W72HN3.js";
|
|
12
12
|
|
|
13
13
|
// src/governance/version-service.ts
|
|
14
14
|
import { createHash } from "crypto";
|
|
@@ -215,6 +215,25 @@ async function setApprovedVersion(nestId, nodeId, version, approvedBy) {
|
|
|
215
215
|
);
|
|
216
216
|
await db.run(sql, [nestId, nodeId, version, approvedBy]);
|
|
217
217
|
}
|
|
218
|
+
var APPROVED_HEAL_AUTHOR = "system:approved-heal";
|
|
219
|
+
async function moveApprovedVersion(nestId, nodeId, from, to) {
|
|
220
|
+
const db = getDb();
|
|
221
|
+
const moved = await db.run(
|
|
222
|
+
`UPDATE approved_versions
|
|
223
|
+
SET approved_version = ?, approved_by = ?, approved_at = ${nowExpr(db)}
|
|
224
|
+
WHERE nest_id = ? AND node_id = ? AND approved_version = ?`,
|
|
225
|
+
[to, APPROVED_HEAL_AUTHOR, nestId, nodeId, from]
|
|
226
|
+
);
|
|
227
|
+
if (moved.changes === 0) return false;
|
|
228
|
+
const note = `Approved version moved from v${from} to v${to} \u2014 v${from} could not be rebuilt`;
|
|
229
|
+
await db.run(
|
|
230
|
+
`UPDATE node_versions
|
|
231
|
+
SET change_note = CASE WHEN change_note IS NULL OR change_note = '' THEN ? ELSE change_note || ' \xB7 ' || ? END
|
|
232
|
+
WHERE nest_id = ? AND node_id = ? AND version = ?`,
|
|
233
|
+
[note, note, nestId, nodeId, to]
|
|
234
|
+
);
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
218
237
|
async function getSealedVersion(nestId, nodeId) {
|
|
219
238
|
const approved = await getApprovedVersion(nestId, nodeId);
|
|
220
239
|
if (approved != null) return approved;
|
|
@@ -458,6 +477,8 @@ export {
|
|
|
458
477
|
getApprovedVersion,
|
|
459
478
|
getApprovedVersions,
|
|
460
479
|
setApprovedVersion,
|
|
480
|
+
APPROVED_HEAL_AUTHOR,
|
|
481
|
+
moveApprovedVersion,
|
|
461
482
|
getSealedVersion,
|
|
462
483
|
deleteSupersededDrafts,
|
|
463
484
|
deleteUnsealedVersions,
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sendEmailToRecipient
|
|
3
|
+
} from "./chunk-RXCVXG34.js";
|
|
4
|
+
import {
|
|
5
|
+
config,
|
|
6
|
+
getDb
|
|
7
|
+
} from "./chunk-H3W72HN3.js";
|
|
8
|
+
import {
|
|
9
|
+
normalizeEmail
|
|
10
|
+
} from "./chunk-FRQJWGN3.js";
|
|
11
|
+
|
|
12
|
+
// src/auth/invited-user.ts
|
|
13
|
+
import { v4 as uuid } from "uuid";
|
|
14
|
+
|
|
1
15
|
// src/auth/keys.ts
|
|
2
16
|
import { randomBytes, createHash, timingSafeEqual } from "crypto";
|
|
3
17
|
import bcrypt from "bcryptjs";
|
|
@@ -124,6 +138,40 @@ function normalizeKeyLabel(raw) {
|
|
|
124
138
|
return trimmed;
|
|
125
139
|
}
|
|
126
140
|
|
|
141
|
+
// src/auth/invited-user.ts
|
|
142
|
+
async function createInvitedUser(rawEmail, opts = {}) {
|
|
143
|
+
const email = normalizeEmail(rawEmail);
|
|
144
|
+
const id = uuid();
|
|
145
|
+
const tempPassword = uuid().replace(/-/g, "").slice(0, 16);
|
|
146
|
+
await getDb().run(
|
|
147
|
+
"INSERT INTO users (id, email, name, password_hash, is_invited) VALUES (?, ?, ?, ?, 1)",
|
|
148
|
+
[id, email, null, await hashPassword(tempPassword)]
|
|
149
|
+
);
|
|
150
|
+
const base = (opts.baseUrl || config.PUBLIC_BASE_URL || "").replace(/\/$/, "");
|
|
151
|
+
void sendEmailToRecipient(email, {
|
|
152
|
+
status: "invited",
|
|
153
|
+
docTitle: "ContextNest",
|
|
154
|
+
path: "",
|
|
155
|
+
actor: email,
|
|
156
|
+
by: opts.invitedBy || void 0,
|
|
157
|
+
tempPassword,
|
|
158
|
+
promptowlSignIn: config.PROMPTOWL_SIGN_IN_GATE === "open",
|
|
159
|
+
// ?invite= prefills the login page and guides them to sign in.
|
|
160
|
+
link: base ? `${base}/?invite=${encodeURIComponent(email)}` : ""
|
|
161
|
+
});
|
|
162
|
+
return { id, tempPassword };
|
|
163
|
+
}
|
|
164
|
+
async function findOrCreateInvitedUser(rawEmail, opts = {}) {
|
|
165
|
+
const email = normalizeEmail(rawEmail);
|
|
166
|
+
const existing = await getDb().get(
|
|
167
|
+
"SELECT id FROM users WHERE LOWER(email) = ?",
|
|
168
|
+
[email]
|
|
169
|
+
);
|
|
170
|
+
if (existing) return { id: existing.id, created: false };
|
|
171
|
+
const { id } = await createInvitedUser(email, opts);
|
|
172
|
+
return { id, created: true };
|
|
173
|
+
}
|
|
174
|
+
|
|
127
175
|
export {
|
|
128
176
|
generateApiKey,
|
|
129
177
|
hashApiKey,
|
|
@@ -131,6 +179,7 @@ export {
|
|
|
131
179
|
parseBearerToken,
|
|
132
180
|
hashPassword,
|
|
133
181
|
verifyPassword,
|
|
134
|
-
|
|
135
|
-
|
|
182
|
+
verifyKeyRequest,
|
|
183
|
+
createInvitedUser,
|
|
184
|
+
findOrCreateInvitedUser
|
|
136
185
|
};
|