@promptowl/contextnest-community 1.13.0 → 1.15.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.
@@ -27,6 +27,7 @@ if (envFileLoaded && !isTestRun) {
27
27
  var canonicalEnvFile = process.env.ENV_FILE_PATH || join(dataRoot(), ".env");
28
28
  var canonicalEnvLoaded = null;
29
29
  var slackUrlWarned = false;
30
+ var msteamsUrlWarned = false;
30
31
  var emailFromWarned = false;
31
32
  var emailToWarned = false;
32
33
  var oidcIssuerWarned = false;
@@ -355,6 +356,27 @@ var config = {
355
356
  }
356
357
  return raw;
357
358
  },
359
+ /**
360
+ * Optional Microsoft Teams incoming-webhook URL (Workflows app) for team
361
+ * notifications — same events as SLACK_WEBHOOK_URL, posted as Adaptive
362
+ * Cards. Empty/unset = connector off. https only — a webhook carries an
363
+ * implicit secret in its path, so it never travels plaintext. Named
364
+ * MSTEAMS_* deliberately: "teams" in this codebase means user groups.
365
+ */
366
+ get MSTEAMS_WEBHOOK_URL() {
367
+ const raw = process.env.MSTEAMS_WEBHOOK_URL?.trim();
368
+ if (!raw) return null;
369
+ if (!/^https:\/\//i.test(raw)) {
370
+ if (!msteamsUrlWarned) {
371
+ msteamsUrlWarned = true;
372
+ console.warn(
373
+ "[config] MSTEAMS_WEBHOOK_URL rejected: must be an https:// URL. Microsoft Teams notifications disabled."
374
+ );
375
+ }
376
+ return null;
377
+ }
378
+ return raw;
379
+ },
358
380
  get FEATURE_WORKFLOW_PLANE() {
359
381
  return process.env.FEATURE_WORKFLOW_PLANE === "true";
360
382
  },
@@ -689,6 +711,12 @@ function runMigrations(db) {
689
711
  if (!nestCols.includes("allow_self_approve")) {
690
712
  db.exec("ALTER TABLE nests ADD COLUMN allow_self_approve INTEGER NOT NULL DEFAULT 0");
691
713
  }
714
+ if (!nestCols.includes("prime_only_review")) {
715
+ db.exec("ALTER TABLE nests ADD COLUMN prime_only_review INTEGER NOT NULL DEFAULT 0");
716
+ }
717
+ if (!nestCols.includes("prime_tags")) {
718
+ db.exec("ALTER TABLE nests ADD COLUMN prime_tags TEXT NOT NULL DEFAULT 'prime-document'");
719
+ }
692
720
  const userCols = db.prepare("PRAGMA table_info(users)").all().map((c) => c.name);
693
721
  if (!userCols.includes("is_admin")) {
694
722
  db.exec("ALTER TABLE users ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0");
@@ -1432,6 +1460,53 @@ function runMigrations(db) {
1432
1460
  })();
1433
1461
  recordMigration("031_team_source");
1434
1462
  }
1463
+ if (!hasMigration("032_deletion_requests")) {
1464
+ db.transaction(() => {
1465
+ db.exec(`
1466
+ CREATE TABLE IF NOT EXISTS deletion_requests (
1467
+ id TEXT PRIMARY KEY,
1468
+ nest_id TEXT NOT NULL REFERENCES nests(id) ON DELETE CASCADE,
1469
+ node_id TEXT NOT NULL,
1470
+ requested_by TEXT NOT NULL, -- email
1471
+ reason TEXT NOT NULL,
1472
+ status TEXT NOT NULL DEFAULT 'pending'
1473
+ CHECK(status IN ('pending', 'declined')),
1474
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
1475
+ resolved_by TEXT, -- email
1476
+ resolved_at TEXT,
1477
+ resolution_note TEXT
1478
+ );
1479
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_deletion_requests_pending
1480
+ ON deletion_requests(nest_id, node_id) WHERE status = 'pending';
1481
+ CREATE INDEX IF NOT EXISTS idx_deletion_requests_nest
1482
+ ON deletion_requests(nest_id, status);
1483
+ `);
1484
+ })();
1485
+ recordMigration("032_deletion_requests");
1486
+ }
1487
+ if (!hasMigration("033_deletion_request_targets")) {
1488
+ db.transaction(() => {
1489
+ const cols = db.prepare("PRAGMA table_info(deletion_requests)").all().map((c) => c.name);
1490
+ if (!cols.includes("target_type")) {
1491
+ db.exec(
1492
+ "ALTER TABLE deletion_requests ADD COLUMN target_type TEXT NOT NULL DEFAULT 'document'"
1493
+ );
1494
+ }
1495
+ db.exec(`
1496
+ DROP INDEX IF EXISTS idx_deletion_requests_pending;
1497
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_deletion_requests_pending
1498
+ ON deletion_requests(nest_id, target_type, node_id) WHERE status = 'pending';
1499
+ `);
1500
+ })();
1501
+ recordMigration("033_deletion_request_targets");
1502
+ }
1503
+ if (!hasMigration("034_versions_author_status_index")) {
1504
+ db.exec(`
1505
+ CREATE INDEX IF NOT EXISTS idx_versions_author_status
1506
+ ON node_versions(author, status);
1507
+ `);
1508
+ recordMigration("034_versions_author_status_index");
1509
+ }
1435
1510
  }
1436
1511
  function mergeCaseCollidingUsers(db) {
1437
1512
  const groups = db.prepare(
@@ -1649,7 +1724,7 @@ async function initDb() {
1649
1724
  if (config.DB_DRIVER === "postgres") {
1650
1725
  const { Pool } = await import("pg");
1651
1726
  const { PostgresAdapter } = await import("./adapter.postgres-YOODX2BI.js");
1652
- const { runPostgresMigrations } = await import("./migrations.postgres-BRXZY2GE.js");
1727
+ const { runPostgresMigrations } = await import("./migrations.postgres-CYKO5CFV.js");
1653
1728
  const pool = new Pool(buildPgConfig());
1654
1729
  adapter = new PostgresAdapter(pool);
1655
1730
  await runPostgresMigrations(adapter);