@floomhq/signaldash 0.39.17 → 0.39.18

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/README.md CHANGED
@@ -120,7 +120,7 @@ setup installs both from the same pinned npm package
120
120
  the human chose to execute:
121
121
 
122
122
  ```bash
123
- npx -y @floomhq/signaldash@0.39.17 <invite-code>
123
+ npx -y @floomhq/signaldash@0.39.18 <invite-code>
124
124
  ```
125
125
 
126
126
  Run that command in a terminal, not in an agent chat. Do not ask an agent to
@@ -401,9 +401,9 @@ first comment. `li_delete_post_draft` requires the current version and
401
401
  `confirm:true`. None of these operations calls LinkedIn, Unipile, Buffer, or an
402
402
  action-budget lane.
403
403
 
404
- `li_post_draft_preview` returns a short-lived, one-use
404
+ `li_post_draft_preview` returns a one-use
405
405
  `https://signaldash.dev/d/<token>` link for one exact saved draft. POSTing its
406
- confirmation creates a 15-minute cookie restricted to `/drafts`; the page and
406
+ confirmation creates a review-duration cookie restricted to `/drafts`; the page and
407
407
  its `/drafts/:id/attachments/:index` media route remain bound to that tenant,
408
408
  draft, and originating live SignalDash session. Media is served byte-for-byte
409
409
  with `private, no-store`, MIME allowlisting, `nosniff`, and a restrictive CSP.
@@ -412,7 +412,7 @@ same cards as scheduled posts, marked by a visible `DRAFT` tag and an
412
412
  `Unscheduled` time label. Saved SignalDash media uses separate protected
413
413
  `/calendar/drafts/...` URLs. Each saved SignalDash draft also exposes an
414
414
  authenticated edit-and-feedback form. Its CSRF token is bound to the live
415
- 60-minute calendar session, draft UUID, and current version. Copy edits,
415
+ calendar review session, draft UUID, and current version. Copy edits,
416
416
  feedback, and up to four private feedback images use one atomic
417
417
  compare-and-swap. Inline saves keep the active filter and scroll position;
418
418
  the server-rendered fallback returns to the same card. Uploaded images are
@@ -473,7 +473,7 @@ only the provider's validated HTTPS media hosts and never exposes a provider
473
473
  URL in browser HTML. Calendar media is no-store and becomes unavailable when
474
474
  the session expires or the originating user is revoked.
475
475
 
476
- `li_scheduled_post_preview` returns a short-lived, single-use browser handoff
476
+ `li_scheduled_post_preview` returns a single-use browser handoff
477
477
  for one exact active SignalDash post owned by the authenticated user. The page
478
478
  shows only that post, including its stored image attachments. Preview sessions
479
479
  and media routes remain account- and post-scoped, expire independently, and
@@ -481,8 +481,11 @@ are revoked on logout. New exact-post links use
481
481
  `https://signaldash.dev/p/<token>` and calendar links use
482
482
  `https://signaldash.dev/c/<token>`. Each new compact token is 8 base64url
483
483
  characters generated from 6 random bytes. Calendar, scheduled-post preview,
484
- and draft-preview handoffs default to a 60-minute unopened-link lifetime,
485
- configurable with `SIGNALDASH_CALENDAR_HANDOFF_TTL_MS`. Their 48 bits of entropy
484
+ and draft-preview handoffs default to a 60-minute unopened-link and browser-session
485
+ lifetime. Pass `review_ttl_hours:24` to any of the four review-link tools for an
486
+ exact 24-hour handoff and resulting session. Only `1` and `24` are accepted;
487
+ the persistence boundary caps both at 24 hours. The default remains configurable
488
+ with `SIGNALDASH_CALENDAR_HANDOFF_TTL_MS`. Their 48 bits of entropy
486
489
  are bounded by one-use consumption and a durable five-attempt
487
490
  per-client throttle. Already-issued 24-character compact tokens and 48-character
488
491
  `/scheduled-post/h/<token>` or `/calendar/h/<token>` links remain valid until
package/bin/sd.mjs CHANGED
@@ -1791,8 +1791,12 @@ const TOOLS = [
1791
1791
  {
1792
1792
  name: "li_post_drafts",
1793
1793
  path: "/li/post_drafts",
1794
- description: "List this account's durable SignalDash LinkedIn post drafts and return a fresh one-use calendar link. Attachment metadata is returned, never base64 bytes. These drafts remain separate from scheduled posts and do not appear in li_scheduled_posts items.",
1795
- inputSchema: { type: "object", properties: {}, additionalProperties: false },
1794
+ description: "List this account's durable SignalDash LinkedIn post drafts and return a fresh one-use calendar link. Pass review_ttl_hours:24 for a 24-hour handoff and browser review session; the default is 1 hour. Attachment metadata is returned, never base64 bytes. These drafts remain separate from scheduled posts and do not appear in li_scheduled_posts items.",
1795
+ inputSchema: {
1796
+ type: "object",
1797
+ properties: { review_ttl_hours: { type: "integer", enum: [1, 24] } },
1798
+ additionalProperties: false,
1799
+ },
1796
1800
  },
1797
1801
  {
1798
1802
  name: "li_update_post_draft",
@@ -1853,11 +1857,12 @@ const TOOLS = [
1853
1857
  {
1854
1858
  name: "li_post_draft_preview",
1855
1859
  path: "/li/post_draft_preview",
1856
- description: "Create a short-lived one-use browser link for one exact saved SignalDash LinkedIn draft. The isolated read-only page renders only that draft, its protected stored images, and its draft first comment.",
1860
+ description: "Create a one-use browser link for one exact saved SignalDash LinkedIn draft. Pass review_ttl_hours:24 for a 24-hour handoff and browser session; the default is 1 hour. The isolated read-only page renders only that draft, its protected stored images, and its draft first comment.",
1857
1861
  inputSchema: {
1858
1862
  type: "object",
1859
1863
  properties: {
1860
1864
  id: { type: "string", format: "uuid" },
1865
+ review_ttl_hours: { type: "integer", enum: [1, 24] },
1861
1866
  },
1862
1867
  required: ["id"],
1863
1868
  additionalProperties: false,
@@ -1866,8 +1871,12 @@ const TOOLS = [
1866
1871
  {
1867
1872
  name: "li_scheduled_posts",
1868
1873
  path: "/li/scheduled_posts",
1869
- description: "Read the shared LinkedIn content calendar from SignalDash and the configured Buffer channel. Always inspect completeness and per-source state. Native LinkedIn scheduled posts and drafts are NOT visible because Unipile has no documented read route for them, and SignalDash does not use raw Voyager routes or linkedin.com browser access. An empty items array is never proof that the native LinkedIn calendar is empty.",
1870
- inputSchema: { type: "object", properties: {}, additionalProperties: false },
1874
+ description: "Read the shared LinkedIn content calendar from SignalDash and the configured Buffer channel. Pass review_ttl_hours:24 for a 24-hour one-use handoff and browser review session; the default is 1 hour. Always inspect completeness and per-source state. Native LinkedIn scheduled posts and drafts are NOT visible because Unipile has no documented read route for them, and SignalDash does not use raw Voyager routes or linkedin.com browser access. An empty items array is never proof that the native LinkedIn calendar is empty.",
1875
+ inputSchema: {
1876
+ type: "object",
1877
+ properties: { review_ttl_hours: { type: "integer", enum: [1, 24] } },
1878
+ additionalProperties: false,
1879
+ },
1871
1880
  },
1872
1881
  {
1873
1882
  name: "li_profile",
@@ -1937,11 +1946,12 @@ const TOOLS = [
1937
1946
  {
1938
1947
  name: "li_scheduled_post_preview",
1939
1948
  path: "/li/scheduled_post_preview",
1940
- description: "Create a short-lived one-use browser link for one exact active SignalDash scheduled post. The preview renders only that post, its stored image attachments, and its queued first comment in a read-only session. Requires the exact SignalDash post UUID returned by li_draft_post or li_scheduled_posts.",
1949
+ description: "Create a one-use browser link for one exact active SignalDash scheduled post. Pass review_ttl_hours:24 for a 24-hour handoff and browser session; the default is 1 hour. The preview renders only that post, its stored image attachments, and its queued first comment in a read-only session. Requires the exact SignalDash post UUID returned by li_draft_post or li_scheduled_posts.",
1941
1950
  inputSchema: {
1942
1951
  type: "object",
1943
1952
  properties: {
1944
1953
  id: { type: "string", format: "uuid" },
1954
+ review_ttl_hours: { type: "integer", enum: [1, 24] },
1945
1955
  },
1946
1956
  required: ["id"],
1947
1957
  additionalProperties: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floomhq/signaldash",
3
- "version": "0.39.17",
3
+ "version": "0.39.18",
4
4
  "description": "Secure LinkedIn, WhatsApp, and email access for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -451,14 +451,14 @@ Use the exact tool names and argument keys below. Limits are optional.
451
451
  | `li_draft_post` | `text` required, max 3000; `publish` optional; `scheduled_at` optional offset-qualified ISO date-time; `content_pipeline_id` normally required for scheduling while that user's pipeline is enabled; `content_pipeline_override` optional exact `{reason,confirm?,approval_hash?}`; `mentions` optional array of up to 25 exact `{name,profile_id}` objects; `attachments` optional array of up to 20 exact `{filename,content_type,content_base64}` images, max 5 MiB each and 12 MiB total; `first_comment` optional, max 1250 | Create a server-confirmed draft, publish now, or persist an exact future LinkedIn post and its approved first comment. An enabled pipeline normally runs its fact, exact-text, shared-calendar, frequency, and breathing preflight. For one deliberate exception, preview the exact payload with `{reason}`, show it to the human, then repeat it with `confirm:true` and the returned single-use payload-bound `approval_hash`. The audit record preserves the reason, preview ID, and approval time; every non-pipeline provider safety guard remains active. |
452
452
  | `li_set_scheduled_post_first_comment` | `id` required UUID; `first_comment` required, max 1250; `confirm:true` required | Attach one exact approved first comment to a scheduled post. SignalDash publishes it through the same connected account after the post and never republishes the post if the comment fails. |
453
453
  | `li_save_post_draft` | `text` required, max 3000; `mentions` optional up to 25; `attachments` optional up to 20 exact images, max 5 MiB each and 12 MiB total; `first_comment` optional, max 1250; `source_key` optional tenant-scoped idempotency key, max 256; `metadata` optional bounded structured source/editorial context | Persist one arbitrary LinkedIn draft without scheduling or publishing. Exact ordered image bytes and ordinary duplicate drafts are retained. An identical `source_key` replay returns the existing draft; changed content under that key is refused. Tenant limits are 1,000 drafts and 100 MiB decoded attachment bytes. No provider call or action budget is used. |
454
- | `li_post_drafts` | no arguments | List durable SignalDash drafts with attachment metadata, never base64, and return a fresh one-use calendar link. The calendar uses the scheduled-post card design for unscheduled SignalDash and Buffer drafts, with a visible `DRAFT` tag. Its 60-minute review session saves copy, notes, and up to four private feedback images inline without reloading the calendar. Reviewers can explicitly replace the post's current images with those uploads; unchecked uploads remain private references. Each SignalDash draft card also displays its exact version and next verified free 08:00 UTC slot. `Approve & schedule` rechecks the complete SignalDash and Buffer calendar, then atomically moves the exact draft into that slot without a provider call. Stored drafts remain separate from scheduled posts until this explicit approval succeeds. |
454
+ | `li_post_drafts` | optional `review_ttl_hours` (`1` or `24`) | List durable SignalDash drafts with attachment metadata, never base64, and return a fresh one-use calendar link. The default handoff and review session last 60 minutes; pass `24` for a full day. The calendar uses the scheduled-post card design for unscheduled SignalDash and Buffer drafts, with a visible `DRAFT` tag. Its review session saves copy, notes, and up to four private feedback images inline without reloading the calendar. Reviewers can explicitly replace the post's current images with those uploads; unchecked uploads remain private references. Each SignalDash draft card also displays its exact version and next verified free 08:00 UTC slot. `Approve & schedule` rechecks the complete SignalDash and Buffer calendar, then atomically moves the exact draft into that slot without a provider call. Stored drafts remain separate from scheduled posts until this explicit approval succeeds. |
455
455
  | `li_update_post_draft` | `id`, complete replacement `text`, and current `expected_version` required; `mentions`, `attachments`, and `first_comment` optional | Atomically replace the complete saved draft. A stale version is refused with the current version and timestamp. Omitting an optional field clears it. No provider call occurs. |
456
456
  | `li_delete_post_draft` | `id`, current `expected_version`, and `confirm:true` required | Permanently delete one exact saved SignalDash draft. Unknown, foreign, deleted, and replayed identifiers are indistinguishable. This cannot delete LinkedIn-native or scheduled content. |
457
- | `li_post_draft_preview` | `id` required UUID | Create a short-lived, single-use `https://signaldash.dev/d/<token>` browser handoff for one exact saved draft. Its page and exact image bytes are protected by a tenant-, draft-, and originating-session-scoped cookie under `/drafts`. |
458
- | `li_scheduled_posts` | no arguments | Read one shared content-calendar view across SignalDash and the configured Buffer LinkedIn channel. The browser calendar renders validated Buffer company tags both inline and as audit pills, and proxies supported Buffer image previews through its authenticated no-store media route without exposing provider URLs. Inspect `completeness` and every `sources.*.state` before treating absence as an empty calendar. Native LinkedIn scheduled posts and drafts are invisible because Unipile has no documented read route for them; SignalDash does not use raw Voyager routes or linkedin.com browser access. An empty `items` array proves only that the visible sources returned no entries. |
457
+ | `li_post_draft_preview` | `id` required UUID; optional `review_ttl_hours` (`1` or `24`) | Create a single-use `https://signaldash.dev/d/<token>` browser handoff for one exact saved draft. The default is 1 hour; pass `24` for a full day. Its page and exact image bytes are protected by a tenant-, draft-, and originating-session-scoped cookie under `/drafts`. |
458
+ | `li_scheduled_posts` | optional `review_ttl_hours` (`1` or `24`) | Read one shared content-calendar view across SignalDash and the configured Buffer LinkedIn channel. The returned one-use calendar link and resulting browser session default to 60 minutes; pass `24` for a full day. The browser calendar renders validated Buffer company tags both inline and as audit pills, and proxies supported Buffer image previews through its authenticated no-store media route without exposing provider URLs. Inspect `completeness` and every `sources.*.state` before treating absence as an empty calendar. Native LinkedIn scheduled posts and drafts are invisible because Unipile has no documented read route for them; SignalDash does not use raw Voyager routes or linkedin.com browser access. An empty `items` array proves only that the visible sources returned no entries. |
459
459
  | `li_profile` | `identifier` required, a public id or member id | Read one LinkedIn profile: name, headline, public identifier, provider id, network distance and the profile picture url. Read-only, one provider call, and it returns those six fields rather than the provider's whole record about a person. It exists because pictures were otherwise a by-product of engagement only: reactions and comments carry one, the stored connections carry no picture field, chats carry none, and the invitation preview refuses anyone already connected, so every new name in a shortlist stayed faceless. |
460
460
  | `sd_share_list` | `action` create/list/revoke, plus `title`, `columns`, `rows`, optional `note`, or `token` to revoke | Share one selection as a standalone `https://signaldash.dev/l/<token>` page that anyone with the link can open. `create` returns the url ONCE and stores only its SHA-256 hash, so a lost link can be revoked but never recovered. The page is a fixed snapshot and never re-reads the source, so a list shared today does not keep disclosing tomorrow's data. Pass `people` instead of `rows` for a shortlist of humans: each renders as a card with a photo where the provider supplies one and initials where it does not, an optional `score` out of 100, and the `reason` that earned it, with the scoring rule in `rubric` so the reader can check it. For a plain table, every row must have exactly as many cells as there are columns, because a crooked table reads as a claim about the wrong person. `list` shows every live link with its non-secret `list_id` and open count, so a link whose url is lost can still be switched off and a forgotten one stays visible; `revoke` takes either the `token` or that `list_id` and kills it immediately, and a revoked token is indistinguishable from one that never existed. |
461
- | `li_scheduled_post_preview` | `id` required UUID | Create a short-lived, single-use `https://signaldash.dev/p/<token>` browser handoff for one exact active SignalDash post. The isolated page includes its stored image attachments through account- and post-scoped protected media routes. |
461
+ | `li_scheduled_post_preview` | `id` required UUID; optional `review_ttl_hours` (`1` or `24`) | Create a single-use `https://signaldash.dev/p/<token>` browser handoff for one exact active SignalDash post. The default is 1 hour; pass `24` for a full day. The isolated page includes its stored image attachments through account- and post-scoped protected media routes. |
462
462
  | `li_edit_scheduled_post` | `id`, `text`, and offset-qualified `scheduled_at` required; full replacement `mentions` (up to 25), image `attachments` (up to 20, max 5 MiB each and 12 MiB total), and `first_comment` optional; confirmation repeats the identical payload with `confirm:true`, `approval_hash`, `expected_version`, and `expected_updated_at` from preview | Atomically replace one scheduled post in place. The UUID, creation time, provider account, and content-pipeline audit fields remain unchanged. A changed or non-scheduled row is refused, approval is single-use and expires, and no provider call occurs. Omitting an optional replacement field clears it. Duplicate identity covers the complete normalized payload, including exact attachment bytes, and only active scheduled or executing rows participate; cancelled history never blocks a replacement. |
463
463
  | `li_cancel_scheduled_post` | `id` required UUID; `confirm:true` required | Cancel one exact post while it is still scheduled. It cannot recall an executing or published post. |
464
464
  | `sd_schedule_message` | `channel` required, `whatsapp` or `linkedin`; `chat_id` required, max 500; `text` required, max 5000; `scheduled_at` required offset-qualified ISO date-time from 60 seconds to 365 days ahead; `confirm:true` required | Schedule one exact message into one chat you have already read. Read that exact chat first, at `limit` 10 or more on LinkedIn: SignalDash records what the thread looked like and refuses at send time if the conversation moved. Text only; attachments are refused rather than dropped. One message at one time, never a sequence. |