@ironfang/n8n-nodes-ironfang 0.4.3 → 0.5.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.
- package/README.md +22 -10
- package/dist/lib/renderwolf.js +4 -4
- package/dist/nodes/Ironfang/catalog.js +7 -16
- package/dist/nodes/Ironfang/credentialTest.js +6 -2
- package/dist/nodes/Ironfang/transport.js +18 -3
- package/docs/operations.md +5 -5
- package/docs/validation.md +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,13 @@ Use Ironfang Render, Finance, Audit and Rig, and Ironfang's public developer
|
|
|
6
6
|
tools, in n8n. The Ironfang action node has **162 operations**, grouped by
|
|
7
7
|
product. Ironfang Trigger receives signed Audit, Finance and Render events.
|
|
8
8
|
|
|
9
|
-
**Release: 0.
|
|
9
|
+
**Release: 0.5.0.** Ironfang billing moved from credits to metered usage, and
|
|
10
|
+
the node follows: a render reports the billing meter and quantity it counted
|
|
11
|
+
instead of credits, Render Usage returns the month per meter, and a billing
|
|
12
|
+
refusal keeps its code, product, meter and renewal date. Workflows that read
|
|
13
|
+
`_ironfang.creditsCharged` need changing; see
|
|
14
|
+
[Permissions and usage](#permissions-and-usage). 0.4.3 reads cache status and
|
|
15
|
+
webhook signatures from the `X-Ironfang-*` and `Ironfang-*` headers. 0.4.2 moved the API to `api.ironfang.com` (credentials saved with the old `api.ironfang.uk` address keep working unchanged), and 0.4.1 made the package installable on n8n releases
|
|
10
16
|
before 2.33 that use PostgreSQL; see [Installation](#installation-and-credentials).
|
|
11
17
|
It includes 0.4.0, in which the products are named Ironfang Render, Finance and Audit
|
|
12
18
|
(formerly Renderwolf, Financewolf and Auditwolf), and the node follows: requests
|
|
@@ -137,13 +143,17 @@ also applies to these outputs.
|
|
|
137
143
|
Keys created with the earlier `renderwolf:*`, `financewolf:*` and `auditwolf:*`
|
|
138
144
|
scopes keep working: the platform treats them as the scopes above.
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
Usage is billed to your organisation's Ironfang billing account, which every
|
|
147
|
+
Ironfang product shares. There are no plans or credits: each kind of work counts
|
|
148
|
+
against a meter with a monthly free allowance, and usage beyond it is billed
|
|
149
|
+
monthly once paid usage is switched on in Billing in the
|
|
150
|
+
[Ironfang portal](https://portal.ironfang.com). A Render screenshot, PDF or
|
|
151
|
+
template image counts 1 on its own meter, clips and site previews count output
|
|
152
|
+
seconds, and QR codes are counted but never charged. Cache hits count nothing.
|
|
153
|
+
Render Usage returns the month for each meter; limits, payment and statements
|
|
154
|
+
are managed in the portal.
|
|
155
|
+
|
|
156
|
+
Public tools are not billed to an account and share a 60/minute/address limit. The
|
|
147
157
|
public screenshot service also has a 20/hour/address limit and a shared daily
|
|
148
158
|
ceiling. Shared n8n egress addresses share these limits. Use authenticated
|
|
149
159
|
Render rendering for account-based automation.
|
|
@@ -202,8 +212,10 @@ fields. Version 1.1 uses numeric `bytes` and structured errors; version 1.2 adds
|
|
|
202
212
|
paging to the Audit lists named above and is otherwise identical. Version 2,
|
|
203
213
|
which new nodes use, behaves as 1.2 does. All expose exact
|
|
204
214
|
`byteLength`, item links and `_ironfang` response metadata when available:
|
|
205
|
-
request ID, HTTP status, cache status and
|
|
206
|
-
|
|
215
|
+
request ID, HTTP status, cache status, and the billing `meter` and `quantity`
|
|
216
|
+
the request counted (0 for a cache hit). Continued errors include available
|
|
217
|
+
problem codes and retry information; a billing refusal also carries `product`,
|
|
218
|
+
`meter` and `resetAt` (when the free allowance renews) when the API states them. New file operations use
|
|
207
219
|
numeric sizes; the output binary field defaults to `data`.
|
|
208
220
|
|
|
209
221
|
Requests have explicit timeouts: 30 seconds for JSON (100 for a Rig wait) and
|
package/dist/lib/renderwolf.js
CHANGED
|
@@ -80,7 +80,7 @@ exports.renderwolf = {
|
|
|
80
80
|
{
|
|
81
81
|
name: 'Usage',
|
|
82
82
|
value: 'usage',
|
|
83
|
-
description: '
|
|
83
|
+
description: "This month's usage of each Render meter, from your billing account",
|
|
84
84
|
action: 'Get usage',
|
|
85
85
|
}, {
|
|
86
86
|
name: 'Video Clip',
|
|
@@ -167,7 +167,7 @@ exports.renderwolf = {
|
|
|
167
167
|
name: 'no_cache',
|
|
168
168
|
type: 'boolean',
|
|
169
169
|
default: false,
|
|
170
|
-
description: 'Whether to force a live capture instead of reusing an identical recent render. Use when the page must be captured exactly as it is right now, such as evidence or change detection.
|
|
170
|
+
description: 'Whether to force a live capture instead of reusing an identical recent render. Use when the page must be captured exactly as it is right now, such as evidence or change detection. A fresh render is always counted.',
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
displayName: 'Quality',
|
|
@@ -204,7 +204,7 @@ exports.renderwolf = {
|
|
|
204
204
|
name: 'no_cache',
|
|
205
205
|
type: 'boolean',
|
|
206
206
|
default: false,
|
|
207
|
-
description: 'Whether to force a live capture instead of reusing an identical recent render. Use when the page must be captured exactly as it is right now, such as evidence or change detection.
|
|
207
|
+
description: 'Whether to force a live capture instead of reusing an identical recent render. Use when the page must be captured exactly as it is right now, such as evidence or change detection. A fresh render is always counted.',
|
|
208
208
|
},
|
|
209
209
|
{
|
|
210
210
|
displayName: 'Print Background',
|
|
@@ -330,7 +330,7 @@ exports.renderwolf = {
|
|
|
330
330
|
type: 'options',
|
|
331
331
|
default: 'vertical',
|
|
332
332
|
displayOptions: { show: { operation: ['video'] } },
|
|
333
|
-
description: '
|
|
333
|
+
description: 'Counted in output seconds: vertical and landscape as 1080p, square and 720p as HD',
|
|
334
334
|
options: [
|
|
335
335
|
{ name: '720p 1280x720', value: '720p' },
|
|
336
336
|
{ name: 'Landscape 1920x1080', value: 'landscape' },
|
|
@@ -1338,7 +1338,7 @@ exports.operations = [
|
|
|
1338
1338
|
"product": "auditwolf",
|
|
1339
1339
|
"id": "getUsage",
|
|
1340
1340
|
"name": "Usage",
|
|
1341
|
-
"description": "
|
|
1341
|
+
"description": "This month's metered use, capacity and hosted evidence",
|
|
1342
1342
|
"method": "GET",
|
|
1343
1343
|
"path": "/v1/usage",
|
|
1344
1344
|
"scope": "audit:read",
|
|
@@ -2011,27 +2011,18 @@ exports.operations = [
|
|
|
2011
2011
|
"product": "financewolf",
|
|
2012
2012
|
"id": "getEinvoiceUsage",
|
|
2013
2013
|
"name": "Usage",
|
|
2014
|
-
"description": "
|
|
2014
|
+
"description": "Read Ironfang Finance usage for a month",
|
|
2015
2015
|
"method": "GET",
|
|
2016
2016
|
"path": "/v1/einvoices/usage",
|
|
2017
2017
|
"scope": "finance:billing:manage",
|
|
2018
2018
|
"query": [
|
|
2019
2019
|
{
|
|
2020
|
-
"name": "
|
|
2021
|
-
"label": "
|
|
2020
|
+
"name": "period",
|
|
2021
|
+
"label": "Period",
|
|
2022
2022
|
"type": "string",
|
|
2023
|
-
"required":
|
|
2024
|
-
"default": "",
|
|
2025
|
-
"description": "RFC3339 inclusive start / exclusive end; at most 366 days.",
|
|
2026
|
-
"enum": []
|
|
2027
|
-
},
|
|
2028
|
-
{
|
|
2029
|
-
"name": "end",
|
|
2030
|
-
"label": "End",
|
|
2031
|
-
"type": "string",
|
|
2032
|
-
"required": true,
|
|
2023
|
+
"required": false,
|
|
2033
2024
|
"default": "",
|
|
2034
|
-
"description": "
|
|
2025
|
+
"description": "A past or current UTC calendar month as YYYY-MM; the current month when omitted.",
|
|
2035
2026
|
"enum": []
|
|
2036
2027
|
}
|
|
2037
2028
|
],
|
|
@@ -3327,7 +3318,7 @@ exports.operations = [
|
|
|
3327
3318
|
"product": "rig",
|
|
3328
3319
|
"id": "getUsage",
|
|
3329
3320
|
"name": "Usage",
|
|
3330
|
-
"description": "Runs
|
|
3321
|
+
"description": "Runs, events and metered interactions",
|
|
3331
3322
|
"method": "GET",
|
|
3332
3323
|
"path": "/v1/usage",
|
|
3333
3324
|
"scope": "rig:read",
|
|
@@ -25,11 +25,15 @@ async function credentialTest(credential) {
|
|
|
25
25
|
});
|
|
26
26
|
lastStatus = response.statusCode;
|
|
27
27
|
const body = response.body;
|
|
28
|
-
|
|
28
|
+
// Render usage is a report per billing meter, or {"unmetered": true}.
|
|
29
|
+
const valid = product === 'renderwolf' ? Array.isArray(body?.meters) || body?.unmetered === true : Array.isArray(body?.[checks[product][1]]);
|
|
29
30
|
if (response.statusCode === 200 && valid)
|
|
30
31
|
return { status: 'OK', message: `Connected to Ironfang ${name}. Each operation requires its own scope.` };
|
|
31
|
-
|
|
32
|
+
const code = body?.error?.code ?? body?.code;
|
|
33
|
+
if (response.statusCode === 403 && code === 'insufficient_scope')
|
|
32
34
|
return { status: 'OK', message: `API key authenticated by Ironfang ${name}. The test read is outside its scopes; choose only the scopes your workflow needs.` };
|
|
35
|
+
if (response.statusCode === 403 && code === 'account_not_linked')
|
|
36
|
+
return { status: 'Error', message: 'API key authenticated, but its account belongs to no Ironfang organisation, so its usage cannot be billed. Contact support.' };
|
|
33
37
|
if (response.statusCode !== 401 && response.statusCode !== 404)
|
|
34
38
|
break;
|
|
35
39
|
}
|
|
@@ -32,15 +32,20 @@ function identifier(context, value, itemIndex) {
|
|
|
32
32
|
}
|
|
33
33
|
return encodeURIComponent(id);
|
|
34
34
|
}
|
|
35
|
+
// A billable response names the billing meter it counted against and the
|
|
36
|
+
// quantity it counted there: 1 for most renders, output seconds for video,
|
|
37
|
+
// 0 for a cache hit or an unmetered key.
|
|
35
38
|
function responseMetadata(headers, statusCode) {
|
|
36
39
|
const result = { statusCode };
|
|
37
40
|
if (headers['x-ironfang-request-id'])
|
|
38
41
|
result.requestId = headers['x-ironfang-request-id'];
|
|
39
42
|
if (headers['x-ironfang-cache'])
|
|
40
43
|
result.cacheStatus = headers['x-ironfang-cache'];
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
if (headers['x-ironfang-meter'])
|
|
45
|
+
result.meter = headers['x-ironfang-meter'];
|
|
46
|
+
const quantity = headers['x-ironfang-quantity'];
|
|
47
|
+
if (quantity !== undefined && /^\d+$/.test(quantity))
|
|
48
|
+
result.quantity = Number(quantity);
|
|
44
49
|
return result;
|
|
45
50
|
}
|
|
46
51
|
async function request(options, authenticated = true) {
|
|
@@ -100,6 +105,16 @@ function errorDetails(error, itemIndex) {
|
|
|
100
105
|
const retry = headers['retry-after'];
|
|
101
106
|
if (typeof retry === 'string' && /^\d+$/.test(retry))
|
|
102
107
|
details.retryAfterSeconds = Number(retry);
|
|
108
|
+
// A billing refusal names the product and meter it refused and, for an
|
|
109
|
+
// exhausted free allowance, when the allowance renews. Render and Audit put
|
|
110
|
+
// them in the error object; Finance problems carry them in `billing`.
|
|
111
|
+
const billing = Object.keys(object(problem.billing)).length ? object(problem.billing) : problem;
|
|
112
|
+
if (typeof billing.product === 'string' && /^[a-z]{1,32}$/.test(billing.product))
|
|
113
|
+
details.product = billing.product;
|
|
114
|
+
if (typeof billing.meter === 'string' && /^[a-z0-9_.]{1,64}$/.test(billing.meter))
|
|
115
|
+
details.meter = billing.meter;
|
|
116
|
+
if (typeof billing.reset_at === 'string' && !Number.isNaN(Date.parse(billing.reset_at)))
|
|
117
|
+
details.resetAt = billing.reset_at;
|
|
103
118
|
return details;
|
|
104
119
|
}
|
|
105
120
|
function apiError(context, error, itemIndex) {
|
package/docs/operations.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Operation reference
|
|
2
2
|
|
|
3
|
-
Generated from Ironfang main `
|
|
3
|
+
Generated from Ironfang main `8ec778a0`. Runtime endpoint selection is fixed by this catalogue.
|
|
4
4
|
Complex request bodies use JSON so all supported schema fields remain available. Replace placeholders with your own values.
|
|
5
5
|
|
|
6
6
|
## audit / Archive Monitor
|
|
@@ -608,7 +608,7 @@ Full request contract: https://api.ironfang.com/audit/openapi.yaml
|
|
|
608
608
|
|
|
609
609
|
`GET /audit/v1/usage`. Scope: `audit:read`.
|
|
610
610
|
|
|
611
|
-
|
|
611
|
+
This month's metered use, capacity and hosted evidence
|
|
612
612
|
|
|
613
613
|
Full request contract: https://api.ironfang.com/audit/openapi.yaml
|
|
614
614
|
|
|
@@ -941,11 +941,11 @@ Full request contract: https://api.ironfang.com/finance/openapi.yaml
|
|
|
941
941
|
|
|
942
942
|
`GET /finance/v1/einvoices/usage`. Scope: `finance:billing:manage`.
|
|
943
943
|
|
|
944
|
-
|
|
944
|
+
Read Ironfang Finance usage for a month
|
|
945
945
|
|
|
946
946
|
Full request contract: https://api.ironfang.com/finance/openapi.yaml
|
|
947
947
|
|
|
948
|
-
Query fields: `
|
|
948
|
+
Query fields: `period`.
|
|
949
949
|
|
|
950
950
|
## finance / Validate E-Invoice
|
|
951
951
|
|
|
@@ -1636,7 +1636,7 @@ Full request contract: https://api.ironfang.com/rig/openapi.yaml
|
|
|
1636
1636
|
|
|
1637
1637
|
`GET /rig/v1/usage`. Scope: `rig:read`.
|
|
1638
1638
|
|
|
1639
|
-
Runs
|
|
1639
|
+
Runs, events and metered interactions
|
|
1640
1640
|
|
|
1641
1641
|
Full request contract: https://api.ironfang.com/rig/openapi.yaml
|
|
1642
1642
|
|
package/docs/validation.md
CHANGED
|
@@ -45,6 +45,15 @@ SQLite, which records nothing. `scripts/check-postgres-install.sh` now runs in
|
|
|
45
45
|
CI before release. 224 tests and all three Docker checks passed locally on
|
|
46
46
|
21 September.
|
|
47
47
|
|
|
48
|
+
The 0.5.0 release follows Ironfang main `8ec778a0` (29 September 2026), where
|
|
49
|
+
Render bills by meter rather than credits. `_ironfang` reports `meter` and
|
|
50
|
+
`quantity` from the `X-Ironfang-Meter` and `X-Ironfang-Quantity` headers,
|
|
51
|
+
billing refusals carry the product, meter and allowance renewal alongside the
|
|
52
|
+
code, and the credential test accepts the per-meter usage report. These were
|
|
53
|
+
checked against the API source and the unit tests, not against a live paid
|
|
54
|
+
render. `npm run check` (229 tests), all three Docker checks and `npm audit`
|
|
55
|
+
(zero reported vulnerabilities) passed locally on 29 September.
|
|
56
|
+
|
|
48
57
|
## Automated coverage
|
|
49
58
|
|
|
50
59
|
- 0.4.0 adds cases for routing saved `/renderwolf` and origin bases to the
|
package/package.json
CHANGED