@revenexx/studio-integrations 1.4.1 → 2.1.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +297 -0
  2. package/README.md +2 -1
  3. package/dist/module.json +1 -1
  4. package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +6 -6
  5. package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +134 -131
  6. package/dist/runtime/components/Integrations/CredentialLogo.vue +1 -1
  7. package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +1 -1
  8. package/dist/runtime/components/Integrations/CredentialTypePicker.vue +6 -6
  9. package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +2 -0
  10. package/dist/runtime/components/Integrations/ExpressionInput.vue +90 -11
  11. package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +2 -0
  12. package/dist/runtime/components/Integrations/GroupFrameView.vue +121 -121
  13. package/dist/runtime/components/Integrations/NodeConfigField.vue +20 -5
  14. package/dist/runtime/components/Integrations/NodeInspector.vue +44 -41
  15. package/dist/runtime/components/Integrations/NodePalette.vue +52 -37
  16. package/dist/runtime/components/Integrations/RunActionsMenu.vue +6 -5
  17. package/dist/runtime/components/Integrations/RunDetailPanel.d.vue.ts +7 -0
  18. package/dist/runtime/components/Integrations/RunDetailPanel.vue +14 -2
  19. package/dist/runtime/components/Integrations/RunDetailPanel.vue.d.ts +7 -0
  20. package/dist/runtime/components/Integrations/RunsTable.vue +72 -70
  21. package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +20 -6
  22. package/dist/runtime/components/Integrations/StickyNoteView.vue +1 -0
  23. package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +10 -6
  24. package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +0 -34
  25. package/dist/runtime/components/Integrations/WorkflowEditor.vue +226 -277
  26. package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +0 -34
  27. package/dist/runtime/components/Integrations/WorkflowExportDialog.d.vue.ts +6 -0
  28. package/dist/runtime/components/Integrations/WorkflowExportDialog.vue +71 -0
  29. package/dist/runtime/components/Integrations/WorkflowExportDialog.vue.d.ts +6 -0
  30. package/dist/runtime/components/Integrations/WorkflowImportFileStep.d.vue.ts +8 -0
  31. package/dist/runtime/components/Integrations/WorkflowImportFileStep.vue +95 -0
  32. package/dist/runtime/components/Integrations/WorkflowImportFileStep.vue.d.ts +8 -0
  33. package/dist/runtime/components/Integrations/WorkflowNodeView.vue +5 -4
  34. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +0 -7
  35. package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +2 -2
  36. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +2 -3
  37. package/dist/runtime/components/Integrations/WorkflowsTable.vue +14 -8
  38. package/dist/runtime/composables/useIntegrationsNodes.js +4 -1
  39. package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +3 -1
  40. package/dist/runtime/composables/useIntegrationsWorkflows.js +5 -22
  41. package/dist/runtime/composables/useNow.d.ts +17 -0
  42. package/dist/runtime/composables/useNow.js +16 -0
  43. package/dist/runtime/composables/useWorkflowFile.d.ts +21 -0
  44. package/dist/runtime/composables/useWorkflowFile.js +63 -0
  45. package/dist/runtime/data/expressionEditor.d.ts +11 -1
  46. package/dist/runtime/data/expressionEditor.js +2 -1
  47. package/dist/runtime/data/nodeIcons.d.ts +14 -0
  48. package/dist/runtime/data/nodeIcons.js +57 -14
  49. package/dist/runtime/data/nodeRunData.js +1 -1
  50. package/dist/runtime/data/payloadForm.js +1 -1
  51. package/dist/runtime/i18n/messages/de.json +47 -11
  52. package/dist/runtime/i18n/messages/en.json +47 -11
  53. package/dist/runtime/pages/integrations/audit.vue +3 -3
  54. package/dist/runtime/pages/integrations/credentials/oauth-complete.vue +2 -2
  55. package/dist/runtime/pages/integrations/credentials.vue +17 -5
  56. package/dist/runtime/pages/integrations/index.vue +5 -10
  57. package/dist/runtime/pages/integrations/schedules.vue +24 -13
  58. package/dist/runtime/pages/integrations/templates/index.vue +40 -40
  59. package/dist/runtime/pages/integrations/workflows/[id].vue +324 -324
  60. package/dist/runtime/types/integrations.d.ts +13 -0
  61. package/dist/runtime/utils/cockpitSources.d.ts +68 -1
  62. package/dist/runtime/utils/credentialState.d.ts +15 -7
  63. package/dist/runtime/utils/credentialState.js +4 -12
  64. package/dist/runtime/utils/localize.d.ts +12 -0
  65. package/dist/runtime/utils/localize.js +1 -1
  66. package/dist/runtime/utils/paletteOrder.d.ts +29 -0
  67. package/dist/runtime/utils/paletteOrder.js +46 -0
  68. package/dist/runtime/utils/relativeTime.d.ts +29 -0
  69. package/dist/runtime/utils/relativeTime.js +23 -0
  70. package/dist/runtime/utils/runFeedQuery.d.ts +12 -6
  71. package/dist/runtime/utils/runFeedQuery.js +3 -18
  72. package/dist/runtime/utils/settingValue.d.ts +33 -0
  73. package/dist/runtime/utils/settingValue.js +8 -0
  74. package/dist/runtime/utils/statusStyle.d.ts +8 -8
  75. package/dist/runtime/utils/statusStyle.js +4 -1
  76. package/dist/runtime/utils/workflowFile.d.ts +119 -0
  77. package/dist/runtime/utils/workflowFile.js +192 -0
  78. package/package.json +10 -5
  79. package/dist/runtime/utils/errorPathAdvice.d.ts +0 -60
  80. package/dist/runtime/utils/errorPathAdvice.js +0 -19
package/CHANGELOG.md CHANGED
@@ -1,5 +1,302 @@
1
1
  # @revenexx/studio-integrations
2
2
 
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6ff6833: A workflow can be exported to a file and imported again, into the same environment or
8
+ another: Export as file in a workflow's row actions and in the editor's actions menu, Import
9
+ from file in the New workflow dialog, and Import from file… in the editor to replace a
10
+ workflow's content. The file never carries credentials, secret values or a webhook's
11
+ address; an import creates a paused workflow, or replaces the editor's content as
12
+ unsaved changes that keep each webhook's address and leave an active workflow running
13
+ until a valid version is saved (PO-525).
14
+ - 9721bc2: PO-537: inside a palette folder, the nodes stand in the order their package gives
15
+ them rather than in the alphabetical order of their identifiers.
16
+
17
+ A node that states its place (`paletteOrder` in its manifest) comes first; the rest
18
+ follow in the order the package lists them, which the Integrations API now reports
19
+ as `package_position`; a node for which neither is known still falls back to its
20
+ identifier. So "Send Email" leads Brevo's Email folder instead of "Cancel Scheduled
21
+ Email".
22
+
23
+ Where a folder holds nodes of several packages, each package orders only its own:
24
+ no node takes a place another package's node held. Against an API that does not
25
+ report `package_position` yet, folders keep today's order.
26
+
27
+ - 1820289: A run's record now shows what the run returned per step: one block for each step, under the name it carries on the canvas, in the order of the steps in the workflow — the way the dialog after a run already shows it. Before, the record printed the result as one object keyed by internal node ids, in an order the run never took. A result the workflow's steps cannot account for, because the workflow has changed since the run, say, is still shown whole.
28
+ - 6cc8b71: A node's optional settings fold only after its last required setting. Before, every optional setting from the fourth on was folded wherever it stood, so a setting between two required ones vanished from the middle of the form, and one "Show n optional settings" control opened settings in two separate places. Everything up to the last required setting is now always shown, and the fold is one tail at the end — Brevo's Double Opt-in, for one, now shows "Never on lists" and folds only "Attributes".
29
+ - 664725b: A mapped value in a node's setting can now be changed where it stands. Click it
30
+ to select it, then click it again or press Enter, and it opens as the expression
31
+ it stands for;
32
+ once the caret or the focus leaves it, it reads as its source again. Until now it
33
+ could only be deleted and written again, which for a condition meant retyping the
34
+ whole expression to correct one character (PO-544).
35
+ - 7fd02ea: The node palette's folders now stand alphabetically on every level, in the
36
+ language the studio is shown in and regardless of case. Until now a folder stood
37
+ where its first node's internal identifier fell in the catalogue, so Test Nodes
38
+ appeared between PostBin and Shipcloud. SFTP is no longer pinned directly after
39
+ FTP; the nodes inside a folder keep the order their package gives them (PO-545).
40
+ - 7525758: A Core folder in the node palette is one folder in every language (PO-546). The studio now names the Core folders it knows — Flow, Data, Text & Formats, Files, Web, Messaging, FTP / SFTP — from its own translations, by their English name, so a node that names no folder, or one an older release left registered with an out-of-date name, no longer opens a second folder (_Data_ beside _Daten_, _Flow_ beside _Ablauf_). Every one of them has its own icon. A path of two levels no longer files a node under Integrations — only an app package or a logo does — so Core can nest a folder; a subfolder without a logo shows the first image its nodes carry.
41
+
42
+ ### Patch Changes
43
+
44
+ - ddcbdbd: The Schedules page says why a schedule will not fire, in the Next run column: its
45
+ workflow is inactive or not built, its schedule cannot be read, its timezone is
46
+ unknown, or its rhythm never comes round. Until now every one of these read as a
47
+ bare dash beside a live badge. A paused schedule and one with no schedule set keep
48
+ the dash, because the row already says so (PO-261).
49
+ - ebbc148: Nothing a user sees changes. The module now declares `@solar-icons/vue`, which its
50
+ components already import through `@solar-icons/nuxt`. A host that typechecks and
51
+ sees every `#solar-icons` import reported as a missing export has to declare
52
+ `@solar-icons/vue` itself: the type declaration is generated into the host's own
53
+ `.nuxt`, so it is resolved from the host's dependencies, not this module's (PO-281).
54
+ - fd5a78e: Nothing a user sees changes. The module is linted now, and the first run's fixes ship
55
+ in it: unused imports and dead helpers removed, the pattern that finds `${{ … }}` in a
56
+ setting no longer slows down on long unclosed input, and the OAuth popup renders one
57
+ root element (PO-305).
58
+ - d9f4742: Cancelling a run from its row in either run list now asks first, the way terminating
59
+ already did and the way the run's record asks before both. A cancelled run cannot be
60
+ resumed, only retried from the start, so a slip in the row's menu was as final as a
61
+ terminate (PO-336).
62
+ - 271de84: A run the platform reports as `canceled` — Temporal's spelling — or in another letter case (`COMPLETED`) now reads the same in the Runs list as at its own record. The list used to draw such a run as _failed_ while the record called it _cancelled_ or _succeeded_; both now read the platform's status through one table.
63
+ - 90d9ae3: "How long ago" reads the same everywhere it is shown: the dashboard's Latest executions and
64
+ Needs attention panels, the runs list's Started column and a credential's last
65
+ check. Under ten seconds is "just now", from there to a minute it counts seconds
66
+ ("40s ago") — the dashboard used to say "just now" for the whole minute — and on
67
+ the dashboard and the runs list that count keeps moving between realtime events.
68
+ From thirty days on it is a date in the studio's language instead of a count like
69
+ "412d ago". A timestamp that cannot be read shows "—"; the dashboard used to print
70
+ "NaNd ago" (PO-393).
71
+ - 60ef22a: The Shipcloud package's node icons draw as icons rather than as grey boxes.
72
+
73
+ A node declares its icon as an `mdi:` name and the studio renders Lucide, so the
74
+ two vocabularies are bridged by a table. A name in neither the table nor Lucide's
75
+ own spelling silently becomes a generic box — which is what the Shipcloud package
76
+ got for its nodes. Eight names now map: `truck-delivery`,
77
+ `package-variant-closed-plus`, `map-marker-path`, `package-variant-remove`,
78
+ `truck-check-outline`, `file-document-outline`, `file-plus-outline` and
79
+ `map-marker-radius-outline`.
80
+
81
+ The table also has a test now, including one that fails on an entry pointing at a
82
+ Lucide component that does not exist: a wrong entry looks exactly like a missing
83
+ one, and neither says anything.
84
+
85
+ - 78e99d6: A number typed into a setting's mapped-value mode is kept as a number, not as text
86
+ (PO-521).
87
+
88
+ **A numeric setting has two boxes and only one of them kept the number.** The plain
89
+ one wrote what was typed as a number; the box beside it — the one that also takes a
90
+ value mapped from elsewhere in the workflow — wrote the raw text through. Brightness
91
+ 50 was stored as `"50"`, the workflow saved without a word, and the run stopped with
92
+ `Config field 'brightness' must be of type number.` Nothing in that field could fix
93
+ it, because the field itself is what produced the text. Reported from the Philips Hue
94
+ **Set Light** node, where every value the author touched was text and the one they
95
+ left at its default was a number.
96
+
97
+ The rule now lives in one place: a numeric setting keeps the number, an emptied box
98
+ is no value rather than `''`, a mapped value is left exactly as it was typed, and
99
+ text denoting no number is kept as typed so the operator sees what they wrote rather
100
+ than finding the box silently emptied. Text in one of the three base notations —
101
+ `0x10`, `0b101`, `0o17` — counts as no number here, since the platform refuses it on
102
+ the way in and storing 16, 5 or 15 would put a value in the workflow nobody typed.
103
+
104
+ **When the conversion happens differs by box, and has to.** The plain one converts as
105
+ it is typed. The mapped-value box shows a document rather than a line of text, and it
106
+ re-projects that document whenever it disagrees with the value it is given — so it
107
+ stores what was typed and converts when it is left. Converting there on every
108
+ keystroke would rebuild the document under the operator's cursor: a number typed over
109
+ what the box already held would keep only its last digit, and `0.4` could never be
110
+ typed at all, because half-way through it is `0.` — a number worth `0`, whose text has
111
+ no dot in it. The range a
112
+ setting allows is read through the same rule, so a workflow **saved before this
113
+ change** — its number still stored as text — is marked in the dialog instead of
114
+ reading as sound until the run refuses it.
115
+
116
+ A yes/no setting has the same shape of defect and is deliberately untouched; it is
117
+ recorded in the Gaps of `specs/node-configuration.md`, with why.
118
+
119
+ The platform half of PO-521 ships separately: cross-validation now reads a numeric
120
+ setting's value as the number it denotes, which is what lets the workflows already
121
+ saved this way run again without anything rewriting them.
122
+
123
+ - 2632bae: A credential type's logo sits in a smaller box: 8 px larger than the symbol instead of
124
+ 16, so 24 px on the Credentials list instead of 32, with the type picker and the
125
+ credential dialogs shrinking in step. The generic key shown for a type without a logo
126
+ shrinks with it (PO-527).
127
+ - 1159568: PO-542: nodes whose icon the studio could not translate no longer draw as an
128
+ empty box.
129
+
130
+ Node packages name their icons in one vocabulary and the studio draws another, so
131
+ each name goes through a table; a name missing from it fell back to the generic box
132
+ without a word. The table now covers the names the packages ship today — all of
133
+ Philips Hue and PostBin, sixteen Brevo nodes, the notifications nodes, and one each
134
+ in core and DeepL. The four chat brands (Discord, Microsoft Teams, Telegram,
135
+ WhatsApp) have no counterpart in the drawing set and get a neutral messaging
136
+ symbol; their vendor logo still marks them.
137
+
138
+ ## 2.0.0
139
+
140
+ ### Major Changes
141
+
142
+ - 8397d7b: Every studio list is read as a table, its search box states its own name, and the Runs
143
+ filter works again on `@revenexx/studio-shared` 0.3.2 (PO-233).
144
+
145
+ **A row of any studio list used to be an unnamed sequence of values.** The shared table
146
+ rendered anonymous boxes, so nothing connected a column heading to the cell beneath it:
147
+ a schedule read as _"Order sync, Daily at 03:00, Europe/Berlin, in 18m, 1h ago, live"_,
148
+ with nothing saying which of the two times was the next run. Taking `studio-shared`
149
+ 0.3.2 gives every list — Workflows, Runs, Schedules, Credentials, Secrets and the Audit
150
+ Log — `table`, `row`, `columnheader` and `cell`, so each value is announced under the
151
+ heading it belongs to. The search above each list now states its name on the field
152
+ itself, in the words of its own placeholder, instead of leaving the browser to work one
153
+ out from that placeholder — which is a fallback rather than a name, and a documented
154
+ failure pattern when it is the only one.
155
+
156
+ **Two cells on the Schedules page lost the labels they carried.** They were there so a
157
+ test could find them, and a name on a cell is read _instead of_ its contents — so with
158
+ the semantics in place they announced "Next run" where the time should be. The heading
159
+ above the column says which time it is now, which is what it is for.
160
+
161
+ **The Runs filter is rebuilt as two selects.** In 0.3.2 the shared filter trigger opens
162
+ a popover rather than a dropdown menu, and the sub-menus this page put inside it had no
163
+ menu to attach to: they rendered nothing at all, so the control was there and the
164
+ narrowing was gone. Outcome and trigger kind are now chosen from a select each, `All`
165
+ included, and the narrowing reaches the platform exactly as before.
166
+
167
+ **A host also owes the shared table two new catalogue entries.** `studio-shared`
168
+ translates through the host's own `shared.*` catalogue and renders the key itself when
169
+ an entry is missing, and 0.3.2 asks for `shared.datatable.toolbar.filter.apply` and
170
+ `…toolbar.filter.reset` — the two buttons of the filter panel, which a host without
171
+ them draws as the key names. The cockpit already carries both, in either language; any
172
+ other host has to add them. (`…toolbar.search.aria.label` is asked for too, but no list
173
+ in this module reaches it: the table names the search box after its own placeholder
174
+ unless a surface says otherwise, and all six pass a placeholder.)
175
+
176
+ **This is a major for two of the reasons [`docs/versioning.md`](docs/versioning.md)
177
+ names.** The peer floor on `@revenexx/studio` rises from `*` to `^0.2.3`, so a host on
178
+ the old range can no longer install — and four accessible names are removed rather than
179
+ renamed: `Next run`, `Last run`, `When it fires` and `Cron expression`, which anything
180
+ addressing a schedules cell by name was using. Both are things a host has to react to.
181
+
182
+ **Hosts must be on `@revenexx/studio` ^0.2.3.** The peer range was `*` and is now the
183
+ version that carries the search field's `label` prop; below it the name falls through to
184
+ a wrapper and the box stays anonymous.
185
+
186
+ - c651aac: The editor no longer points out an error output nobody connected. The run says it instead
187
+ (PO-479).
188
+
189
+ **What goes.** A strip above the canvas read _"{n} node routes failures to an output with
190
+ nothing attached — nothing handles the failure there."_, named each step, and offered to
191
+ attach a **Stop and Error** step to the port in one click. The strip, that action, and the
192
+ five promises in `specs/workflow-advice.md` are withdrawn.
193
+
194
+ **Why, and what an author loses.** The strip and the platform behaviour it described
195
+ shipped together under PO-443. The platform half is the one that can speak with authority:
196
+ a failure routed to an output nothing leaves now **ends the run**, naming the step, what it
197
+ failed with, and which output had nowhere to send it — the `node-failure-handling` spec of
198
+ `revenexx/integrations`, AC-8. Before PO-443 such a failure vanished and the run was
199
+ recorded as a success, which is the world the strip was built for and which no longer
200
+ exists. What is genuinely lost is the timing: an author used to be told while drawing, and
201
+ is now told by the first run that actually fails.
202
+
203
+ **`revenexx:stop-and-error` is untouched.** It is still in the palette, still what all eight
204
+ shipped templates put behind each of their twenty-five error ports, and still the right
205
+ thing to attach. Only the editor's one-click attachment is gone.
206
+
207
+ **A major, for the reason [`docs/versioning.md`](docs/versioning.md) gives.** Seven strings
208
+ are removed rather than renamed, and three of them are accessible names or an action label
209
+ that a host or a test could be addressing:
210
+
211
+ | Removed | What it was |
212
+ | ------------------------------------------ | ------------------------------------------- |
213
+ | `integration.editor.errorPath.advice` | the strip's own sentence |
214
+ | `integration.editor.errorPath.action.stop` | _Stop the run on error_ |
215
+ | `integration.editor.errorPath.ariaReveal` | accessible name of the step link |
216
+ | `integration.editor.errorPath.ariaFix` | accessible name of the attach action |
217
+ | `integration.editor.errorPath.more` | _…and {n} more_ |
218
+ | `integration.editor.errorPath.message` | the pre-filled message on the attached step |
219
+ | `integration.editor.errorPath.toast.added` | the toast after attaching |
220
+
221
+ Nothing else in the editor moves: the validation banner, the reauth strip and the build
222
+ notice keep their place above the canvas, and the activation gate is unchanged — the strip
223
+ never touched it, which was the whole point of it.
224
+
225
+ ### Patch Changes
226
+
227
+ - a79380d: The dialog that imports a platform SFTP account can be drawn by any host built to the
228
+ written contract, and its wait is now a promise with a test behind it (PO-387).
229
+
230
+ **The studio's written contract for a host was five members behind what this dialog
231
+ reads.** `src/runtime/utils/cockpitSources.ts` says what the module expects of a cockpit
232
+ host, and its `sftp` entry declared neither `loading` nor `activeTenantSlug`, made
233
+ `load`'s tenant argument required where the cockpit makes it optional, and left `server`
234
+ and `home_directory` off an account. The dialog read all five. The cockpit has provided
235
+ all five throughout, so **nothing was ever wrong for an operator** — what was wrong is
236
+ that a host built to the contract instead of to the cockpit threw
237
+ `TypeError: Cannot read properties of undefined` while drawing the dialog. Vue's error
238
+ handler turns that into a console message and unmounts the tree, so the page went blank
239
+ with no error anything could catch.
240
+
241
+ **The consequence was that no test could reach the surface at all.** The playground's
242
+ stand-in for the cockpit is built from the contract, so switching it on crashed the
243
+ dialog and leaving it off gave a dialog that never waits — the only two states the suite
244
+ could produce. The waiting announcement PO-251 added here was therefore recorded as a
245
+ gap rather than a criterion. The contract and the stand-in now carry all five members,
246
+ the dialog takes its type from the contract rather than declaring its own, and
247
+ `specs/node-configuration.md` carries the wait as AC-33 with a test that fails when the
248
+ announcement is taken away.
249
+
250
+ **A failed fetch no longer reads as a tenant with no accounts.** The surrounding
251
+ application catches its own fetch errors, so the studio is handed an empty list and no
252
+ exception — and the dialog drew the same "No active platform SFTP accounts. Create one
253
+ under Integration Studio → SFTP first." for both. One of those two asks the operator to
254
+ go and create an account; the other does not, and nothing on screen let them tell which
255
+ they were looking at. The contract gains the `error` the cockpit has always exposed —
256
+ **optional**, because the standalone dev studio's stand-ins provide the other four
257
+ members and not that one, and a dialog that insisted on it would lose that host the
258
+ whole surface. Where it is absent the dialog keeps the empty state it showed before.
259
+ That is AC-34, and it adds one string in both languages: **"The platform SFTP accounts could not be loaded:
260
+ {message}"** / "Die Plattform-SFTP-Konten konnten nicht geladen werden: {message}".
261
+
262
+ **A patch.** `CockpitSftpAccount` gains two required members, which
263
+ [`docs/versioning.md`](docs/versioning.md) would put in the major column as a narrowed
264
+ type — but only for somebody who can reach it. Nobody can: `exports` in `package.json`
265
+ declares `"."` alone and no `typesVersions`, so every other subpath is sealed and
266
+ `require.resolve` of the file answers `ERR_PACKAGE_PATH_NOT_EXPORTED`. The type ships
267
+ inside the tarball and is importable from nowhere. The dialog reads exactly what it read
268
+ before, so a host that worked goes on working unchanged.
269
+
270
+ - 8975a1f: The Credentials list offers the provider step to a credential that never took it, not
271
+ only to one whose authorisation expired (PO-478).
272
+
273
+ **A three-legged credential is created before its provider is asked.** The dialog closes
274
+ on the creation, and the window that asks for consent is opened after that — so when
275
+ that second step fails, there is no dialog left to say so. What remained was a
276
+ credential that cannot work, wearing the same _Not Connected_ badge as one nobody has
277
+ tested, with nothing in its row to finish what was started. The only way on was to
278
+ delete it and make it again.
279
+
280
+ **The row now offers the step wherever a three-legged credential is not known to be
281
+ connected**, and the wording says which of the two it is: **Connect** where nothing has
282
+ ever proved the credential connected, **Reconnect** where it was working and stopped —
283
+ an authorisation that expired, or a connection test that failed. The amber stays on the
284
+ expired one, which is the case this surface has always marked for attention. A
285
+ credential whose access data is a key, a host or a password never carries either, which
286
+ is what keeps the offer from becoming background noise.
287
+
288
+ It is generous by exactly one case: a credential that _was_ authorised but never tested
289
+ also carries the offer, because nothing the service returns tells that apart from one
290
+ that was never authorised. Taking the step again is the same window the operator was
291
+ expecting, so the cost of that guess is a click.
292
+
293
+ Promised behaviour: `specs/credentials.md` AC-2. The `## Gaps` entry in
294
+ `specs/credential-create.md` that asked what this surface says when the step after the
295
+ close fails is answered, and now points here.
296
+
297
+ - c787791: No product change: a spec's `## Gaps` entry and a test comment now say only what was
298
+ measured about `canvas-navigation` AC-4 (PO-479).
299
+
3
300
  ## 1.4.1
4
301
 
5
302
  ### Patch Changes
package/README.md CHANGED
@@ -74,7 +74,7 @@ component styling silently breaks:
74
74
  Adjust the relative paths to reach `node_modules` from your CSS file.
75
75
 
76
76
  ## Peers
77
- `@revenexx/studio`, `@revenexx/studio-shared` ^0.2 (module form), `nuxt` ^4, `vue` ^3.5,
77
+ `@revenexx/studio` ^0.2.3, `@revenexx/studio-shared` ^0.3.2 (module form), `nuxt` ^4, `vue` ^3.5,
78
78
  `@vue-flow/*` + `@dagrejs/dagre` (workflow editor), `lucide-vue-next`; register
79
79
  `@solar-icons/nuxt` in the host.
80
80
 
@@ -86,6 +86,7 @@ cockpit monorepo under `packages/studio-integrations`).
86
86
  ```bash
87
87
  pnpm install # runs the module `prepare` (nuxt-module-build)
88
88
  pnpm test # vitest
89
+ pnpm lint # eslint — `pnpm lint --fix` fixes what has a fix, layout above all
89
90
  pnpm build # dist/
90
91
  pnpm changeset # record what your change does to the version
91
92
  ```
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revenexx/studio-integrations",
3
3
  "configKey": "studioIntegrations",
4
- "version": "1.4.1",
4
+ "version": "2.1.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -149,16 +149,16 @@ async function submit() {
149
149
  {{ t("integration.credentials.createDialog.noTypeAvailable") }}
150
150
  </p>
151
151
  <button
152
- v-for="t in allowedTypes"
153
- :key="t.slug"
152
+ v-for="type in allowedTypes"
153
+ :key="type.slug"
154
154
  type="button"
155
155
  class="flex w-full items-center gap-2 rounded-lg border border-black/[0.08] p-3 text-left transition hover:border-black/20 hover:bg-muted/30"
156
- @click="pickType(t)"
156
+ @click="pickType(type)"
157
157
  >
158
- <IntegrationsCredentialLogo :type="t" :size="18" />
158
+ <IntegrationsCredentialLogo :type="type" :size="18" />
159
159
  <div class="min-w-0 truncate text-sm">
160
- <span class="font-semibold">{{ resolveLocalized(t.name) }}</span>
161
- <span class="ml-1.5 text-muted-foreground">({{ authKindLabel(t.auth_kind) }})</span>
160
+ <span class="font-semibold">{{ resolveLocalized(type.name) }}</span>
161
+ <span class="ml-1.5 text-muted-foreground">({{ authKindLabel(type.auth_kind) }})</span>
162
162
  </div>
163
163
  </button>
164
164
  </div>