instar 1.3.561 → 1.3.562

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.
@@ -3,6 +3,10 @@
3
3
  *
4
4
  * Prevents prompt injection, path traversal, and SSRF attacks
5
5
  * by validating and cleaning user-controlled fields before use.
6
+ *
7
+ * CONTRACT-EVIDENCE: EXEMPT — pure string-validation/slug helpers; this module
8
+ * makes NO Slack API calls and touches no API-contract surface. The added
9
+ * slugifyChannelName is covered by tests/unit/slack-channel-slug.test.ts.
6
10
  */
7
11
  /**
8
12
  * Sanitize a Slack display name for safe injection into session context.
@@ -21,6 +25,19 @@ export declare function validateChannelId(id: string): boolean;
21
25
  * Must be lowercase alphanumeric with hyphens/underscores, max 80 chars.
22
26
  */
23
27
  export declare function validateChannelName(name: string): boolean;
28
+ /**
29
+ * Slugify an arbitrary string into a valid Slack channel name.
30
+ *
31
+ * Slack channel names must be lowercase and may only contain [a-z0-9-_]
32
+ * (see {@link validateChannelName}). A workspace-derived name like
33
+ * "SageMind Live Test" contains spaces and uppercase, which `createChannel`
34
+ * rejects via validate-and-throw. This produces a guaranteed-valid slug:
35
+ * lowercase, non-[a-z0-9] runs collapsed to a single hyphen, leading/trailing
36
+ * hyphens trimmed, and clamped to Slack's 80-char limit.
37
+ *
38
+ * Mirrors the session-channel slug logic in SlackAdapter.
39
+ */
40
+ export declare function slugifyChannelName(name: string): string;
24
41
  /**
25
42
  * Validate that a URL hostname belongs to *.slack.com.
26
43
  * Used to prevent SSRF via manipulated upload URLs.
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../../src/messaging/slack/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../../src/messaging/slack/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD"}
@@ -3,6 +3,10 @@
3
3
  *
4
4
  * Prevents prompt injection, path traversal, and SSRF attacks
5
5
  * by validating and cleaning user-controlled fields before use.
6
+ *
7
+ * CONTRACT-EVIDENCE: EXEMPT — pure string-validation/slug helpers; this module
8
+ * makes NO Slack API calls and touches no API-contract surface. The added
9
+ * slugifyChannelName is covered by tests/unit/slack-channel-slug.test.ts.
6
10
  */
7
11
  const CHANNEL_ID_PATTERN = /^[CDG][A-Z0-9]{8,12}$/;
8
12
  const CHANNEL_NAME_PATTERN = /^[a-z0-9][a-z0-9\-_]{0,79}$/;
@@ -36,6 +40,25 @@ export function validateChannelId(id) {
36
40
  export function validateChannelName(name) {
37
41
  return CHANNEL_NAME_PATTERN.test(name);
38
42
  }
43
+ /**
44
+ * Slugify an arbitrary string into a valid Slack channel name.
45
+ *
46
+ * Slack channel names must be lowercase and may only contain [a-z0-9-_]
47
+ * (see {@link validateChannelName}). A workspace-derived name like
48
+ * "SageMind Live Test" contains spaces and uppercase, which `createChannel`
49
+ * rejects via validate-and-throw. This produces a guaranteed-valid slug:
50
+ * lowercase, non-[a-z0-9] runs collapsed to a single hyphen, leading/trailing
51
+ * hyphens trimmed, and clamped to Slack's 80-char limit.
52
+ *
53
+ * Mirrors the session-channel slug logic in SlackAdapter.
54
+ */
55
+ export function slugifyChannelName(name) {
56
+ return name
57
+ .toLowerCase()
58
+ .replace(/[^a-z0-9]+/g, '-')
59
+ .replace(/^-+|-+$/g, '')
60
+ .slice(0, 80);
61
+ }
39
62
  /**
40
63
  * Validate that a URL hostname belongs to *.slack.com.
41
64
  * Used to prevent SSRF via manipulated upload URLs.
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../src/messaging/slack/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AACnD,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAC3D,4CAA4C;AAC5C,MAAM,aAAa,GAAG,kBAAkB,CAAC;AACzC,MAAM,eAAe,GAAG,UAAU,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI;SACR,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,IAAI,EAAE;SACN,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../src/messaging/slack/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AACnD,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAC3D,4CAA4C;AAC5C,MAAM,aAAa,GAAG,kBAAkB,CAAC;AACzC,MAAM,eAAe,GAAG,UAAU,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI;SACR,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,IAAI,EAAE;SACN,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;AACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.561",
3
+ "version": "1.3.562",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-14T10:35:51.901Z",
5
- "instarVersion": "1.3.561",
4
+ "generatedAt": "2026-06-14T11:06:11.902Z",
5
+ "instarVersion": "1.3.562",
6
6
  "entryCount": 201,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,46 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The boot helpers that auto-create the Slack "Updates" and "Attention" channels
9
+ (`ensureSlackUpdatesChannel` / `ensureSlackAttentionChannel` in
10
+ `src/commands/server.ts`) passed a raw, workspace-derived name straight into
11
+ `SlackAdapter.createChannel`. When the workspace name contained spaces or
12
+ uppercase (e.g. "SageMind Live Test"), that produced an invalid Slack channel
13
+ name like `SageMind Live Test-sys-updates`, which `createChannel` rejects via
14
+ `validateChannelName` — so the channel never got created and the boot logged
15
+ `Failed to create Slack Updates channel: Invalid channel name`.
16
+
17
+ Both callers now slugify the name first through a new shared
18
+ `slugifyChannelName` helper in `src/messaging/slack/sanitize.ts` (lowercase,
19
+ collapse non-`[a-z0-9]` runs to a single hyphen, trim edge hyphens, clamp to
20
+ Slack's 80-char limit) — mirroring the per-session channel slug logic the
21
+ adapter already used on its `-sess-` path. The `createChannel` /
22
+ `validateChannelName` contract other callers rely on is untouched.
23
+
24
+ ## What to Tell Your User
25
+
26
+ If your Slack workspace name has spaces or capital letters and your agent failed
27
+ to create its Updates or Attention channel (an "Invalid channel name" error on
28
+ startup), that's now fixed — the channel name is cleaned into a valid Slack
29
+ slug before creation. Workspaces whose name was already lowercase-and-dashes see
30
+ no change at all.
31
+
32
+ ## Summary of New Capabilities
33
+
34
+ - New `slugifyChannelName(name)` helper in the Slack sanitize module — a single
35
+ source of truth for turning an arbitrary name into a valid Slack channel name.
36
+ - The Slack Updates and Attention boot channels now create reliably regardless
37
+ of workspace-name casing or spaces.
38
+
39
+ ## Evidence
40
+
41
+ - `tests/unit/slack-channel-slug.test.ts` — the exact failing name
42
+ ("SageMind Live Test-sys-updates") now slugifies to a name `validateChannelName`
43
+ accepts; covers lowercasing, space-collapse, punctuation stripping, edge-hyphen
44
+ trim, already-valid passthrough, 80-char clamp, and a regression assertion that
45
+ the raw un-slugified name is rejected.
46
+ - `npx tsc --noEmit` clean; 9/9 new unit tests green.
@@ -0,0 +1,16 @@
1
+ # Why the Slack Updates channel failed to create (and now doesn't)
2
+
3
+ ## The one-sentence version
4
+ When your Slack workspace had a space or a capital letter in its name (like "SageMind Live Test"), the agent tried to make a Slack channel literally named "SageMind Live Test-sys-updates" — but Slack only allows lowercase, no-spaces channel names, so the creation crashed every time. Now the name is cleaned up first.
5
+
6
+ ## Picture it
7
+ Imagine a mailroom that will only accept package labels written in lowercase with dashes instead of spaces. The agent was handing it a label that said "SageMind Live Test-sys-updates" — capital letters, spaces and all — and the mailroom kept rejecting it. The fix is a tiny label-printer that rewrites the label as "sagemind-live-test-sys-updates" before handing it over.
8
+
9
+ ## What changed, precisely
10
+ - The two callers that auto-create the Slack "Updates" and "Attention" channels were passing a raw, workspace-derived name straight into channel creation.
11
+ - That raw name kept its spaces and capitals, which Slack rejects — so the channel never got made and you saw "Invalid channel name".
12
+ - Now both callers run the name through a small slugifier first (lowercase it, turn anything that isn't a-z/0-9 into a single dash, trim stray dashes, cap at Slack's 80-char limit) — exactly the same cleanup the per-session Slack channels already used.
13
+
14
+ ## Why this is safe
15
+ - It only changes how the name is *built* before creation; it does not touch the channel-creation rule that other code relies on (that rule still rejects bad names — it just never sees one now).
16
+ - A name that was already valid passes through unchanged.
@@ -0,0 +1,46 @@
1
+ # Side-Effects Review — Slack Updates/Attention channel name slugify
2
+
3
+ ## Change summary
4
+ Caller-side fix in `src/commands/server.ts`: the `ensureSlackUpdatesChannel` and
5
+ `ensureSlackAttentionChannel` boot helpers now slugify the workspace-derived
6
+ channel name before calling `SlackAdapter.createChannel`, via a new shared
7
+ `slugifyChannelName` helper in `src/messaging/slack/sanitize.ts`. Mirrors the
8
+ existing per-session channel slug logic in `SlackAdapter` (`-sess-` path).
9
+
10
+ ## Tier
11
+ Tier 1 — small, low-risk, single-machine Slack-adapter boot-path bugfix. No
12
+ converged spec required.
13
+
14
+ ## Files touched
15
+ - `src/messaging/slack/sanitize.ts` — adds exported `slugifyChannelName(name)`.
16
+ - `src/commands/server.ts` — imports the helper; wraps both `-sys-updates` and
17
+ `-sys-attention` channel names with it before `createChannel`.
18
+ - `tests/unit/slack-channel-slug.test.ts` — new focused unit test.
19
+
20
+ ## Behavioral side-effects
21
+ - **Channel names on FRESH creation**: a workspace name containing spaces or
22
+ uppercase now yields a slugified channel (e.g. "SageMind Live Test" →
23
+ `sagemind-live-test-sys-updates`) instead of a hard failure. For workspaces
24
+ whose name was already slug-clean (lowercase, no spaces), the produced name is
25
+ byte-identical to before — no change.
26
+ - **No change to `createChannel` / `validateChannelName`**: the validate-and-throw
27
+ behavior other callers depend on is untouched; the fix only ensures these two
28
+ callers never hand it an invalid name.
29
+ - **Idempotent at the state layer**: both helpers early-return when their
30
+ `slack-*-channel` state key is already set, so this only affects the one-time
31
+ creation path; existing installs that already created a channel are unaffected.
32
+
33
+ ## Migration parity
34
+ - No agent-installed file changed (no `.claude/settings.json` hooks, no
35
+ `.instar/config.json` defaults, no CLAUDE.md template, no hook scripts, no
36
+ built-in skills). This is server-side runtime code shipped in the normal
37
+ build — existing agents receive it on their next update with no migration.
38
+
39
+ ## Rollback
40
+ - Revert the squash commit. The change is self-contained (one helper + two call
41
+ sites + one test); no data migration, no state schema change, nothing to undo.
42
+
43
+ ## Blast radius
44
+ - Limited to the Slack adapter boot path. Telegram / WhatsApp / iMessage and all
45
+ non-Slack code paths are untouched. Dark-gate config line-map unchanged (no
46
+ ConfigDefaults edit).