@com55/node-red-ai-access 0.2.0-beta.6 → 0.2.0-beta.7

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/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to
7
7
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.2.0-beta.7] - 2026-10-28
10
+
11
+ ### Fixed
12
+
13
+ - Unrelated flow changes no longer expire or reject pending proposals.
14
+
15
+ ### Added
16
+
17
+ - Automatic three-way rebasing onto live flows, with a `conflict` status that
18
+ blocks approval until resolved.
19
+ - Configurable `proposalTtlDays` (1–365 days, default 7); only TTL expiry closes
20
+ old open proposals.
21
+ - Admin conflict-choice and recheck routes, AI REST resolution, and the MCP
22
+ `resolve_proposal_conflict` tool.
23
+ - Diffs include editor changes and the merged deployment; approval requires a
24
+ `mergedHash` acknowledgement when live changes are merged.
25
+ - Recent known stale revisions are accepted at submit and rebased immediately.
26
+
9
27
  ## [0.2.0-beta.6] - 2026-10-28
10
28
 
11
29
  ### Added
package/README.md CHANGED
@@ -14,10 +14,10 @@ Temporary, owner-approved Node-RED access for AI clients. Ships as a **Node-RED
14
14
  services
15
15
 
16
16
  **Git mental model:** a proposal is like a pull request. Human approve = merge;
17
- reject = close; withdraw = the author closes their own PR. If `rev` /
18
- `expectedRev` does not match, treat it as a conflict: re-read the flow, rebase
19
- the edit, and resubmit. Every access link can see all proposals
20
- (`mine: true|false`).
17
+ reject = close; withdraw = the author closes their own PR. Revision changes
18
+ auto-rebase open proposals. A `conflict` blocks approval until resolved. Open
19
+ proposals expire after a configurable TTL (default 7 days). Every access link
20
+ can see all proposals (`mine: true|false`).
21
21
 
22
22
  Derived from
23
23
  [ziv-daniel/node-red-mcp](https://github.com/ziv-daniel/node-red-mcp).
@@ -46,8 +46,12 @@ Configuration).
46
46
  The `/ai-access` HTML shell is served without adminAuth so the page can read the
47
47
  editor token from browser `localStorage` (Node-RED does not use cookies) and
48
48
  call APIs with `Authorization: Bearer`. If no valid token is present, the page
49
- redirects to the editor login. All data and actions stay behind permission
50
- checks.
49
+ shows a sign-in card. With credentials login, it posts to
50
+ `<httpAdminRoot>/auth/token` as client `node-red-editor` using the password
51
+ grant. The token is shared with the editor, stored under the editor's
52
+ `localStorage` key (`auth-tokens` at `/`, or e.g. `auth-tokens-admin` at
53
+ `/admin`). Other login strategies open the editor to sign in. All data and
54
+ actions stay behind permission checks.
51
55
 
52
56
  The dashboard has tabs for **Overview** (status and diagnostics), **Settings**,
53
57
  **Access tokens**, **OAuth**, **Proposals** and **Audit log**. You can create
@@ -74,6 +78,9 @@ module.exports = {
74
78
  maxActiveLinks: 10,
75
79
  // Deploy type used on approve (default: "nodes"; also "flows" | "full")
76
80
  defaultDeploymentType: 'nodes',
81
+ approveQueueTimeoutMs: 60_000, // maximum time waiting to start approval
82
+ deployTimeoutMs: 60_000, // caller deadline; does not cancel deployment
83
+ deployHardCapMs: 300_000, // release the queue even if deployment never settles
77
84
  // In-memory rate limits for /mcp/api and /mcp/a (per IP + per access token)
78
85
  rateLimitWindowMs: 60000,
79
86
  rateLimitMaxPerIp: 600,
@@ -402,10 +409,43 @@ revoke the link and create a new one. After a restart every old token is
402
409
  invalid.
403
410
 
404
411
  Call `list_flows` or `get_flow` first and pass the returned `rev` as
405
- `expectedRev`. Submit checks the live rev (**409** if stale). Approve may send
406
- `deploymentType`: `nodes` (default), `flows`, or `full`. A stale `expectedRev`
407
- at approve marks the proposal **rejected** with a resubmit message; other deploy
408
- errors mark it **failed**. Reject never mutates flows.
412
+ `expectedRev`. Recent known stale revisions are accepted and auto-rebased;
413
+ unknown revisions return **409** `version_mismatch`. Human approval waits up to
414
+ 60 seconds for deployment. A timeout returns **504** `deploy_timeout`, leaves
415
+ the proposal pending with a persisted `deployPending` reason shown in the API
416
+ and dashboard, and holds the approval queue until the runtime settles or the 5
417
+ minute hard cap is reached. Before the cap, a late success marks the proposal
418
+ approved with its `resultRev`; a late failure clears `deployPending` and keeps
419
+ it pending for retry. At the cap the queue and proposal lock are released,
420
+ `deployPending.queueReleased` becomes true, and the card asks reviewers to check
421
+ the live flow before approving again. Later runtime settlement leaves this
422
+ unknown-outcome record unchanged. Every subsequent approval re-reads live flows
423
+ before rebasing and deploying, recognizing already-applied results. Queued
424
+ approvals time out after 60 seconds with **504** `approve_queue_timeout` without
425
+ deploying. Queued proposals can still be rejected or withdrawn; their approvals
426
+ then return `proposal_not_pending` when dequeued. These three deadlines are
427
+ configurable in `settings.js` under `aiAccess` (positive milliseconds; invalid
428
+ values use the defaults shown above). When choosing **proposed** during conflict
429
+ resolution, unchanged secret spans keep their live editor values. If spans
430
+ cannot be aligned safely, proposed values are retained with a
431
+ `secret_may_revert` warning on the dashboard card. Deliberately deleted secret
432
+ spans do not raise this warning. Deleting one of several identical secret lines
433
+ while their live values changed keeps the proposal in conflict; resolve that
434
+ field against the live flow or choose **live**. Changed env arrays with
435
+ duplicate names show `duplicate_env_keys`, since pairing by name is ambiguous
436
+ when entries are reordered.
437
+
438
+ Open proposals auto-rebase on editor changes. A `conflict` blocks approval until
439
+ resolved using REST `POST /proposals/:id/resolve`, admin
440
+ `POST /proposals/:id/resolve-conflict`, or MCP `resolve_proposal_conflict`.
441
+ Diffs include `rebase`, `liveChanges` and (without conflicts) `vsCurrent`, the
442
+ merged deployment. Approval requires the reviewed `mergedHash` when editor
443
+ changes are merged. Proposals expire after `proposalTtlDays` (integer 1–365,
444
+ default 7), editable through the settings API. Approve may send
445
+ `deploymentType`: `nodes` (default), `flows`, or `full`. Approval rebases
446
+ against the current revision; conflicts leave the proposal open for resolution.
447
+ Deploy timeouts keep it **pending**; other deploy errors mark it **failed**.
448
+ Reject never mutates flows.
409
449
 
410
450
  ### Flow runtime adapter
411
451
 
package/ai-access.html CHANGED
@@ -14,7 +14,7 @@
14
14
  }
15
15
  window.__com55AiAccessSidebarLoading = true;
16
16
 
17
- var EDITOR_SIDEBAR_ASSET_VERSION = '0.2.0-beta.6';
17
+ var EDITOR_SIDEBAR_ASSET_VERSION = '0.2.0-beta.7';
18
18
  var root = (RED.settings.httpAdminRoot || '/').replace(/\/$/, '');
19
19
  var src =
20
20
  (root || '') +